我有一个由以下整数列组成的表:
group_id, person_id, sequence
理想情况下,主键是(group_id, person_id)
,但我需要首先删除一些重复项。每当有重复项时,我只想保留最低的序列值。
我想出了一个查询来选择一些错误的行,但它只获得重复集中的最高序列号。
SELECT COUNT(*) AS num, group_id, person_id, MAX(sequence)
FROM my_table
GROUP BY group_id, person_id
HAVING COUNT(*) > 1;
我确定我错过了一些简单的事情。有没有一种简单的方法可以删除这些副本?
感谢。
答案 0 :(得分:0)
所有列都应重复。因此,分组应用所有列,如
select * from my_table where not EXISTS (
SELECT group_id, person_id, min(sequence)
FROM my_table
GROUP BY group_id, person_id
HAVING COUNT(*) > 1);
答案 1 :(得分:0)
尝试编写一个返回要删除的行的查询。假设(group_id,person_id,sequence)
的组合是UNIQUE,并且您没有NULL值...
SELECT t.*
FROM my_table t
JOIN ( SELECT o.group_id
, o.person_id
, MAX(o.sequence) AS max_sequence
FROM my_table o
GROUP BY o.group_id, o.person_id
HAVING COUNT(*) > 1
) d
ON d.group_id = t.group_id
AND d.person_id = t.person_id
AND d.max_sequence = t.sequence
我们可以将DELETE
关键字替换为SELECT
关键字,将其转换为DELETE
语句。
或者,当我删除带有与此类似的语句的行时,我通常会创建一个表作为我要删除的行的“备份”。
在SELECT CREATE TABLE some_new_table_name AS
之前。
然后,我们可以在DELETE查询中引用“已保存”行
DELETE t.*
FROM my_table t
JOIN some_new_table_name d
ON d.group_id = t.group_id
AND d.person_id = t.person_id
AND d.max_sequence = t.sequence
这种方法只能获得重复的“一个”。如果原始查询的计数值大于2,那么我们需要重复此次,每次删除最高序列值,重复该值,直到没有大于1的计数值。
如果要删除大量重复项,我们可以使用稍微不同的模式一次性获取它们。
我们可以返回MAX(sequence)
,而不是返回MIN(sequence)
(我们要删除的行),而不是我们想要保留的行。我们会改变谓词,
AND d.max_sequence = t.sequence
是
AND d.min_sequence <> t.sequence
因此,对于具有最小值的那个,group_id, person_id
EXCEPT删除所有行。
我强烈建议您先将其写为SELECT
,然后再将其转换为DELETE
语句。我还建议您对表格进行良好备份和/或“保存”要删除的行的副本。以防你需要恢复一些行。