Sql server SQL Server-如何删除总和为零的行对
我需要从一个表中删除一对行,其中数量为零。净额结算应仅在BookCode和ISIN的关键组合内进行 这是原始表格: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 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
和ISIN333
有两行,每行的金额为-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