如何解决仅选择第一个反向重复
我在SQL Server 2014数据库中具有下表:
+----+-------+--------+---------+
| ID | CODE | NUMBER | BALANCE |
+----+-------+--------+---------+
| 1 | B0001 | 122960 | 100.00 |
+----+-------+--------+---------+
| 2 | B0001 | 123168 | -100.00 |
+----+-------+--------+---------+
| 3 | B0001 | 121400 | 500.00 |
+----+-------+--------+---------+
| 4 | T0001 | 19755 | 50.00 |
+----+-------+--------+---------+
| 5 | T0001 | 19975 | -50.00 |
+----+-------+--------+---------+
| 6 | T0001 | 122202 | 50.00 |
+----+-------+--------+---------+
| 7 | T0001 | 122203 | 50.00 |
+----+-------+--------+---------+
我正在尝试选择给定代码的余额可以与另一行偏移并总计为0的行。例如,第1行和第2行的余额总计为0,因此应返回。我已经尝试过以下查询:
SELECT T1.NUMBER
FROM TABLE T1,TABLE T2
WHERE T1.CODE = T2.CODE
AND T1.BALANCE + T2.BALANCE = 0
这对于代码B0001来说可以正常工作。它将返回第1行和第2行,它们彼此抵消,并忽略第3行。代码T0001出现问题,因为我使用的查询会将3个正值中的每一个与负值匹配,并返回所有关联的行该代码。我只希望它返回T0001的第4行和第5行。
解决方法
尝试一下:
/* DATASET MOCK-UP */
DECLARE @Data TABLE ( ID INT,CODE VARCHAR(10),NUMBER INT,BALANCE DECIMAL(18,2) );
INSERT INTO @Data ( ID,CODE,NUMBER,BALANCE ) VALUES
( 1,'B0001',122960,100.00 ),( 2,123168,-100.00 ),( 3,121400,500.00 ),( 4,'T0001',19755,50.00 ),( 5,19975,-50.00 ),( 6,122202,( 7,122203,50.00 );
/*
Return records where combined balances equal 0 by adding the
current record's BALANCE against its previous (lag) or following (lead) balances.
*/
SELECT
ID,BALANCE,( BALANCE + LAG_BALANCE ) AS LAG_BALANCE,( BALANCE + LEAD_BALANCE ) AS LEAD_BALANCE
FROM (
SELECT
ID,LAG ( BALANCE,1,0 ) OVER ( PARTITION BY CODE ORDER BY CODE,ID ) AS LAG_BALANCE,LEAD ( BALANCE,ID ) AS LEAD_BALANCE
FROM @Data
) AS Results
WHERE
BALANCE + LAG_BALANCE = 0
OR
BALANCE + LEAD_BALANCE = 0
ORDER BY
ID;
返回
+----+-------+--------+---------+-------------+--------------+
| ID | CODE | NUMBER | BALANCE | LAG_BALANCE | LEAD_BALANCE |
+----+-------+--------+---------+-------------+--------------+
| 1 | B0001 | 122960 | 100.00 | 100.00 | 0.00 |
| 2 | B0001 | 123168 | -100.00 | 0.00 | 400.00 |
| 4 | T0001 | 19755 | 50.00 | 550.00 | 0.00 |
| 5 | T0001 | 19975 | -50.00 | 0.00 | 0.00 |
| 6 | T0001 | 122202 | 50.00 | 0.00 | 100.00 |
+----+-------+--------+---------+-------------+--------------+
更新: 我只希望可以取消NUMBER个值。对于T0001,返回哪个数字以取消负值并不重要,只要它仅返回一对值即可。例如,对于T0001,它可以返回第4和5、5和6或5和7行。它们都有效,但是我只想要其中之一。
此修改为与您的“归零”条件匹配的每个CODE返回一个数字:
SELECT
CODE,MIN ( NUMBER ) AS MIN_NUMBER
FROM (
SELECT
ID,ID ) AS LEAD_BALANCE
FROM @Data
) AS Results
WHERE
BALANCE + LAG_BALANCE = 0
OR
BALANCE + LEAD_BALANCE = 0
GROUP BY
CODE
ORDER BY
CODE;
返回
+-------+------------+
| CODE | MIN_NUMBER |
+-------+------------+
| B0001 | 122960 |
| T0001 | 19755 |
+-------+------------+
更新#2:
/*
Return the first TWO rows for a CODE with BALANCEs that zero-out each other.
*/
SELECT
ID,ID ) AS LEAD_BALANCE,ROW_NUMBER() OVER ( PARTITION BY CODE ORDER BY CODE,ID ) AS CODE_ROW
FROM @Data
) AS Results
WHERE
CODE_ROW <= 2
AND ( BALANCE + LAG_BALANCE = 0 OR BALANCE + LEAD_BALANCE = 0 )
ORDER BY
ID;
返回
+----+-------+--------+---------+-------------+--------------+
| ID | CODE | NUMBER | BALANCE | LAG_BALANCE | LEAD_BALANCE |
+----+-------+--------+---------+-------------+--------------+
| 1 | B0001 | 122960 | 100.00 | 100.00 | 0.00 |
| 2 | B0001 | 123168 | -100.00 | 0.00 | 400.00 |
| 4 | T0001 | 19755 | 50.00 | 50.00 | 0.00 |
| 5 | T0001 | 19975 | -50.00 | 0.00 | 0.00 |
+----+-------+--------+---------+-------------+--------------+
,
您想以相反的余额匹配行,但每行只能匹配一次。
一个选项是首先用row_number()
枚举行。然后,您可以使用自联接解决方案,在联接条件中添加行号。我更喜欢not exists
-但逻辑是相同的:
with cte as (
select
t.*,row_number() over(partition by code,balance order by id) rn
from mytable t
)
select *
from cte c
where exists (
select 1
from cte c1
where c1.code = c.code and c1.rn = c.rn and c1.balance + c.balance = 0
)
order by code,id
id | code | number | balance | rn -: | :---- | -----: | ------: | -: 1 | B0001 | 122960 | 100.00 | 1 2 | B0001 | 123168 | -100.00 | 1 4 | T0001 | 19755 | 50.00 | 1 5 | T0001 | 19975 | -50.00 | 1,
类似这样的东西
;with
neg_cte as (select *,balance order by id) rn
from @Data where BALANCE<0),pos_cte as (select *,balance order by id) rn
from @Data where BALANCE>0)
select * from neg_cte
union all
select pc.* from neg_cte nc join pos_cte pc on nc.CODE=pc.CODE
and nc.BALANCE=pc.BALANCE*-1
and nc.rn=pc.rn
order by ID;
结果
ID CODE NUMBER BALANCE rn
1 B0001 122960 100.00 1
2 B0001 123168 -100.00 1
4 T0001 19755 50.00 1
5 T0001 19975 -50.00 1
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。