我的下表以这些记录为例:
+------+---------+---------+ | key | amount1 | amount2 | |------|---------|---------| | A | 100 | 0 | | B | 0 | 100 | | C | 100 | 0 | | D | 66 | 34 | | E | 99 | 12 | | F | 100 | 12 | | G | 12 | 99 | +------+---------+---------+
我想删除所有记录,其中一行的字段amount1 =另一行的amount2,但只有成对:如果我找到2条记录,其中amount1 = amount2,那么我可以删除它们,如果我找到了第三条记录我必须保留它。
示例:上面的第一条记录,其中key = A,其中amount1 = 100,amount2 = 0,这里的对将是密钥B,其中amount1 = 0,amount2 = 100. row with key = C必须保留。
+------+---------+---------+ | key | amount1 | amount2 | +------+---------+---------+ | A | 100 | 0 | | B | 0 | 100 | Pair found with key = A : Delete key = A and key = B | C | 100 | 0 | No pair found as the 2 first records compose a pair | D | 66 | 34 | No pair found | E | 99 | 12 | No pair found | F | 100 | 12 | No pair found | G | 12 | 99 | Pair found with key = E : Delete records with key = E and key = G +------+---------+---------+
预期结果如下:
+------+---------+---------+ | key | amount1 | amount2 | +------+---------+---------+ | C | 100 | 0 | | D | 66 | 34 | | F | 100 | 12 | +------+---------+---------+
所以要么我想确定所有对,然后删除它们,要么直接只显示没有对的行。
有任何线索吗?
先谢谢你的帮助,
答案 0 :(得分:0)
一种可行的方法,而不是特别好。
DELETE a
FROM some_table a
INNER JOIN
(
SELECT a.amount1 AS am1,
a.amount2 AS am2,
b.amount1 AS bm1,
b.amount2 AS bm2,
MIN(a.`key`) AS del_key
FROM some_table a
INNER JOIN some_table b
ON a.amount1 = b.amount2
AND a.amount2 = b.amount1
GROUP BY a.amount1,
a.amount2,
b.amount1,
b.amount2
UNION
SELECT a.amount1 AS am1,
a.amount2 AS am2,
b.amount1 AS bm1,
b.amount2 AS bm2,
MIN(b.`key`) del_key
FROM some_table a
INNER JOIN some_table b
ON a.amount1 = b.amount2
AND a.amount2 = b.amount1
GROUP BY a.amount1,
a.amount2,
b.amount1,
b.amount2
) b
ON a.key = b.del_key
这将获得每个键的匹配数量和最小值。然后将此作为子查询作为DELETE语句的一部分与原始表连接。
答案 1 :(得分:0)
像这样的东西。请注意删除amount1 = amount2的行对所需的额外工作量。我在测试数据中添加了一些额外的行来测试查询的正常工作。
我说明了(使用MINUS操作符)显示"剩余"的方法。在"删除"之后的查询中的行(减号)成对的行。类似的东西可以用于DELETE语句 - 尽管更好的做法是使用额外的列flag
来标记成对的行,而不是删除它们(在现实生活中,你不想简单地想要删除历史信息)。
ADDED:此解决方案适用于Oracle;我不知道其他数据库产品可能需要哪些更改(如果有的话)。另外:请注意,在此解决方案中,如果您有两行金额(12,99)和五行金额(99,12),那么在"删除"之后会留下什么?是(99,12)三行。在我看来,这是对这种情况下要求的合理解释。
with
input_data ( key, amount1, amount2 ) as (
select 'A', 100, 0 from dual union all
select 'B', 0, 100 from dual union all
select 'C', 100, 0 from dual union all
select 'D', 66, 34 from dual union all
select 'E', 99, 12 from dual union all
select 'F', 100, 12 from dual union all
select 'G', 12, 99 from dual union all
select 'H', 200, 200 from dual union all
select 'I', 200, 200 from dual union all
select 'J', 200, 200 from dual union all
select 'K', 300, 300 from dual
),
prep ( key, amount1, amount2, rn ) as (
select key, amount1, amount2,
row_number() over (partition by amount1, amount2 order by key)
from input_data
)
select key, amount1, amount2
from input_data
minus
select a.key, a.amount1, a.amount2
from prep a inner join prep b
on
(
a.amount1 = b.amount2
and a.amount2 = b.amount1
and a.amount1 != a.amount2
and a.rn = b.rn
)
or
(
a.amount1 = b.amount2
and a.amount2 = b.amount1
and a.amount1 = b.amount1
and
(
mod(a.rn, 2) = 1
and b.rn = a.rn + 1
)
or
(
mod(a.rn, 2) = 0
and b.rn = a.rn - 1
)
)
;
KEY AMOUNT1 AMOUNT2
--- ---------- ----------
D 66 34
F 100 12
J 200 200
K 300 300