2

我需要从表中消除数量净为零的行对。净额结算只能在 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 的正值配对并不重要。

任何想法都非常感谢!

4

3 回答 3

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
    )
于 2019-03-05T12:40:44.590 回答
0

您可以使用NOT EXISTSand执行此操作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;
于 2019-03-05T12:41:07.830 回答
0

尝试使用PARTITION BYCommon 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
于 2019-03-05T13:26:08.297 回答