我需要从金额净减为零的表中消除成对的行。结帐只能在BookCode和ISIN的键组合内进行。
这是原始表:
BookCode ISIN Reference Amount
ABCD 111 R1 -30
ABCD 111 R2 30
ABCD 222 R3 -25
ABCD 222 R4 -25
ABCD 222 R5 -25
ABCD 222 R6 -25
ABCD 222 R7 25
EFGH 333 R8 -20
EFGH 333 R9 -20
EFGH 444 R10 40
EFGH 444 R11 -40
IJKL 555 R12 -10
这就是我想留下的。...
ABCD 222 R3 -25
ABCD 222 R4 -25
ABCD 222 R5 -25
IJKL 555 R12 -10
对于
ABCD / 222
-25行中的哪一行与R7的正值配对都无关紧要。
任何想法都值得赞赏!
答案 0 :(得分:0)
尝试如下操作,我用row_number将唯一键强加到它上,所以我不确定它是否可以工作,但这似乎是您需要的原理
WITH CTE AS (SELECT row_number() OVER (ORDER BY BookCode) as id, * FROM OrigTab)
DELETE CTE WHERE CTE.id IN
(SELECT c1.id FROM
CTE c1
JOIN
CTE c2
ON
c1.bookcode = c2.bookcode and
c1.id != c2.id and
c1.ISIN = c2.ISIN and
c1.amount+c2.amount = 0
)
或仅查看行
WITH CTE AS (SELECT row_number() OVER (ORDER BY BookCode) as id, * FROM OrigTab)
SELECT * FROM CTE WHERE CTE.id NOT IN
(SELECT c1.id FROM
CTE c1
JOIN
CTE c2
ON
c1.bookcode = c2.bookcode and
c1.id != c2.id and
c1.ISIN = c2.ISIN and
c1.amount+c2.amount = 0
)
答案 1 :(得分:0)
您可以使用NOT EXISTS
和ROW_NUMBER()
进行此操作:
IF OBJECT_ID(N'tempdb..#T', 'U') IS NOT NULL DROP TABLE #T;
CREATE TABLE #T (BookCode VARCHAR(4), ISIN INT, Reference VARCHAR(3), Amount INT);
INSERT INTO #T (BookCode, ISIN, Reference, Amount)
VALUES
('ABCD', 111, 'R1', -30),
('ABCD', 111, 'R2', 30),
('ABCD', 222, 'R3', -25),
('ABCD', 222, 'R4', -25),
('ABCD', 222, 'R5', -25),
('ABCD', 222, 'R6', -25),
('ABCD', 222, 'R7', 25),
('EFGH', 333, 'R8', -20),
('EFGH', 333, 'R9', -20),
('EFGH', 444, 'R10', 40),
('EFGH', 444, 'R11', -40),
('IJKL', 555, 'R12', -10);
WITH RankedData AS
( SELECT *, RowNumber = ROW_NUMBER() OVER(PARTITION BY BookCode, ISIN, Amount ORDER BY Reference DESC)
FROM #T
)
SELECT BookCode, ISIN, Reference, Amount
FROM RankedData AS rd
WHERE NOT EXISTS
( SELECT 1
FROM RankedData AS rd2
WHERE rd2.BookCode = rd.BookCode
AND rd2.ISIN = rd.ISIN
AND rd2.Amount = -rd.Amount
AND rd2.RowNumber = rd.RowNumber
);
输出
BookCode ISIN Reference Amount
------------------------------------------------
ABCD 222 R5 -25
ABCD 222 R4 -25
ABCD 222 R3 -25
EFGH 333 R9 -20
EFGH 333 R8 -20
IJKL 555 R12 -10
ROW_NUMBER()
函数确保每一行只能用于取消另一行,否则,结果中将没有ABCD
的记录。
或者,如果您要删除网记录,而不是仅选择其余记录,则可以使用:
WITH RankedData AS
( SELECT *, RowNumber = ROW_NUMBER() OVER(PARTITION BY BookCode, ISIN, Amount ORDER BY Reference DESC)
FROM #T
)
DELETE rd
FROM RankedData AS rd
WHERE EXISTS
( SELECT 1
FROM RankedData AS rd2
WHERE rd2.BookCode = rd.BookCode
AND rd2.ISIN = rd.ISIN
AND rd2.Amount = -rd.Amount
AND rd2.RowNumber = rd.RowNumber
);
SELECT *
FROM #T;
答案 2 :(得分:0)
尝试使用PARTITION BY
和Common Table Expressions
。
这是一个示例:
DECLARE @Table TABLE
(
BookCode VARCHAR(10),
ISIN int,
Reference VARCHAR(10),
Amount INT
)
INSERT INTO @Table
(
BookCode,
ISIN,
Reference,
Amount
)
VALUES
('ABCD', 111, 'R1', -30)
, ('ABCD', 111, 'R2', 30)
, ('ABCD', 222, 'R3', -25)
, ('ABCD', 222, 'R4', -25)
, ('ABCD', 222, 'R5', -25)
, ('ABCD', 222, 'R6', -25)
, ('ABCD', 222, 'R7', 25)
, ('EFGH', 333, 'R8', -20)
, ('EFGH', 333, 'R9', -20)
, ('EFGH', 444, 'R10', 40)
, ('EFGH', 444, 'R11', -40)
, ('IJKL', 555, 'R12', -10)
和查询:
;WITH ordered AS
(
SELECT
t.BookCode
, t.ISIN
, t.Reference
, t.Amount
, ROW_NUMBER() OVER (PARTITION BY t.BookCode, t.ISIN ORDER BY t.Reference) RN
FROM @Table t
), Pairs AS (
SELECT
o1.Reference c1
, o2.Reference c2
, ROW_NUMBER() OVER (PARTITION BY o1.Reference ORDER BY o1.Reference) RN
FROM ordered o1
INNER JOIN ordered o2
ON o1.Amount = -o2.Amount
AND o1.RN = o1.RN
WHERE o1.Amount > 0
)
DELETE FROM t FROM @Table t
WHERE EXISTS (
SELECT * FROM Pairs p WHERE (p.c1 = t.Reference OR p.c2 = t.Reference AND p.RN = 1)
)
SELECT * FROM @Table t
输出:
BookCode ISIN Reference Amount
ABCD 222 R4 -25
ABCD 222 R5 -25
ABCD 222 R6 -25
EFGH 333 R8 -20
EFGH 333 R9 -20
IJKL 555 R12 -10