我正在尝试编写一个查询,该查询将仅选择没有相反值的行。例如,如果一列(付款)具有2个负数(-11)和3个正数(11),则两个负数将抵消,而一个正数将保留。我可能在解释这个错误。但是任何帮助都值得赞赏。 表格:
CREATE TABLE hamzachecks(
ID VARCHAR(2) NOT NULL
,CHECK VARCHAR(10) NOT NULL
,Payment VARCHAR(8) NOT NULL
);
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('1','9549549544','-112.96');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('2','9549549544','-112.96');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('3','9549549544','112.96');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('4','9549549544','112.96');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('5','9549549544','-165.92');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('6','9549549544','225.92');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('7','9549549544','-299.3');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('8','9549549544','-299.3');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('9','9549549544','-299.3');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('10','9549549544','299.3');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('11','9549549544','299.3');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('12','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('13','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('14','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('15','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('16','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('17','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('18','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('19','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('20','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('21','9549549544','-415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('22','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('23','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('24','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('25','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('26','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('27','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('28','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('29','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('30','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('31','9549549544','415.14');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('32','9549549544','-1024.22');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('33','9549549544','1024.22');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('34','9549549578','-253.77');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('35','9549549578','253.77');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('36','9549549578','-3332.16');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('37','9549549578','-6664.29');
INSERT INTO hamzachecks(ID,CHECK,Payment) VALUES ('38','9549549578','6664.29');
答案 0 :(得分:1)
基本逻辑与@Marty相同,使用相同的chk/payment
组合为每行分配一个行号。
SELECT chk
,id
,Payment
,Row_Number() Over (PARTITION BY chk, Payment ORDER BY Id) AS rn
FROM hamzachecks
order by
chk
-- remove the leading '-'', for numeric data: abs(Payment)
,substring(Payment, charindex('-', Payment)+1, 8000)
,rn
,Payment
有一个匹配的行,两行将共享相同的rn
...
9549549544 3 112.96 1 -- 1st group
9549549544 1 -112.96 1 -- matching value: remove
9549549544 4 112.96 2 -- 2nd group
9549549544 2 -112.96 2 -- matching value: remove
...
9549549544 10 299.3 1 -- 1st group
9549549544 7 -299.3 1 -- matching value: remove
9549549544 11 299.3 2 -- 2nd group
9549549544 8 -299.3 2 -- matching value: remove
9549549544 9 -299.3 3 -- 3rd group, no matching value: keep
...
现在使用聚合删除具有两行的组:
;WITH cte AS
(
SELECT chk
,id
,Payment
,Row_Number() Over (PARTITION BY chk, Payment ORDER BY Id) AS rn
FROM hamzachecks
)
SELECT
Min(id)
,chk
,max(Payment)
FROM cte
GROUP BY
chk
-- remove the leading '-'', for numeric data: abs(Payment)
,substring(Payment, charindex('-', Payment)+1, 8000)
,rn
HAVING count(*) = 1
请参见fiddle
答案 1 :(得分:0)
对于您为什么要以这种特定方式执行此特定工作,我将忽略可能的考虑。
所以基本上:以下SQL将给您您要的结果...
;with b (id, payment, rn) as
(select id, payment, row_number() over (partition by Payment order by Id) as rn
from hamzachecks
where payment < 0),
a (id, payment, rn) as
(select id, payment, row_number() over (partition by Payment order by Id) as rn
from hamzachecks
where payment > 0),
matched_ids (id1,id2) as
(select a.id id1, b.id id2
from a
join b on a.payment = -b.payment and a.rn = b.rn)
select *
from hamzachecks
where id not in (select id1 from matched_ids union select id2 from matched_ids)
order by id
这需要更改架构:将“付款”列定义为MONEY
(或其他数字类型)而不是VARCHAR(8)
。
这将是进一步工作的起点,因为此解决方案忽略了CHECK
列。
说明:首先,我们将源表分为两组:a
-零以上(payment > 0
)和b
-零以下(payment < 0
)。这两个组都将获得另一列row_number() ...
,该列将根据特定组(partition by Payment
)中的位置向每一行获取一个“ rowID”,该行的基本含义是:“这是 n-具有相同付款的行”。然后,联接部分匹配另一组中具有相同(但相反)Payment的所有行,并检查rowID-我们现在知道所有具有相反值的行。因此,主选择仅忽略那些行,而仅返回那些没有相反值的行。