Sql server SQL Server-如何删除总和为零的行对

Sql server SQL Server-如何删除总和为零的行对,sql-server,Sql Server,我需要从一个表中删除一对行,其中数量为零。净额结算应仅在BookCode和ISIN的关键组合内进行 这是原始表格: BookCode ISIN Reference Amount ABCD 111 R1 -30 ABCD 111 R2 30 ABCD 222 R3 -25 ABCD 222 R4 -25

我需要从一个表中删除一对行,其中数量为零。净额结算应仅在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的正值配对并不重要


任何想法都非常感谢

试试下面的方法,我在上面加了一个带有行号的唯一键,所以我不确定它是否有效,但这似乎是你需要的原则

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
    )

您可以使用
不存在
行号()来执行此操作。

输出

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\u NUMBER()
函数可确保每一行只能用于取消另一行,否则结果中将不会有任何记录

或者,如果您希望实际删除已扣除的记录,而不仅仅是选择剩余的记录,您可以使用:

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;

尝试使用
分区方式
通用表表达式

这是一个例子:

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

您的表有主键还是唯一约束?如果没有,为什么不呢?Larnu-不必订购参考资料。我添加它只是为了证明每一行都有一个唯一的引用。在“现实生活”中,这个参考号是一个16个字符的varchar,前3个是字母,其余是数字…Smor-将参考号添加到键中可以有效地使记录唯一。但正如我所说的,我需要在BookCode/ISIN组合中执行净额结算;示例数据误导了我。举一个例子,两个不连续的行“相互抵消”,就很好了。:)对于BookCode
EFGH
和ISIN
333
有两行,每行的金额为-20,因此净额为-40。为什么这不符合您的预期结果?谢谢Cato。我会尝试一下。这确实会删除行-如果你只想不显示它们-等一下,我会发布代码这是一个有趣的问题-我希望这里的答案能帮助你那么我是如何得到这个问题的?我所描述的示例数据实际上是同一个表上两个查询的联合结果,其中第一个Select检索所有行,其中一个名为“开始日期”的列=特定值(业务对象中的提示),第二个选择检索所有行,其中另一个名为“到期日”的列也等于提示中的相同值。区分这两组数据的唯一方法是对从“开始日期”选择检索的行应用负值。正如我所描述的,这样做的目的是消除积极的和消极的一面。
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