删除具有重复主复合键的行
Remove rows with duplicate primary compound key
我有一个 table 由以下整数列组成:
group_id, person_id, sequence
理想情况下,主键应该是 (group_id, person_id)
,但我需要先删除一些重复项。每当有重复时,我只想保留最低的序列值。
我想出一个查询 select 一些错误的行,但它只获得重复集中的最高序列号。
SELECT COUNT(*) AS num, group_id, person_id, MAX(sequence)
FROM my_table
GROUP BY group_id, person_id
HAVING COUNT(*) > 1;
我确定我遗漏了一些简单的东西。有没有简单的方法来删除这些重复项?
谢谢。
所有列都应重复。所以按这样分组应用所有列
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);
尝试编写一个查询,return包含您要删除的行。假设 (group_id,person_id,sequence)
的组合是唯一的,并且您没有 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
我们可以将 SELECT
关键字替换为 DELETE
关键字,从而将其转换为 DELETE
语句。
或者,当我使用与此类似的语句删除行时,我通常会创建一个 table 作为我要删除的行的 "backup"。
在 SELECT 之前加上 CREATE TABLE some_new_table_name AS
。
然后,我们可以在 DELETE 查询中引用 "saved" 行
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
这种方法只能获得 "one" 的重复项。如果原始查询的计数值大于 2,那么我们需要重复此操作足够多次,每次删除最高序列值,重复直到没有大于 1 的计数值。
如果有很多重复项要删除,我们可以使用稍微不同的模式来一次性删除它们。
而不是 returning MAX(sequence)
(我们要删除的行),我们可以 return MIN(sequence)
,我们要保留的行。我们会改变谓词,
AND d.max_sequence = t.sequence
成为
AND d.min_sequence <> t.sequence
因此我们删除 所有 行 group_id, person_id
除了具有最小值的行。
我强烈建议您先将其写成 SELECT
,然后再将其转换为 DELETE
语句。我还建议您对要删除的行的 table and/or "save" 副本进行良好备份。以防万一您需要恢复一些行。
我有一个 table 由以下整数列组成:
group_id, person_id, sequence
理想情况下,主键应该是 (group_id, person_id)
,但我需要先删除一些重复项。每当有重复时,我只想保留最低的序列值。
我想出一个查询 select 一些错误的行,但它只获得重复集中的最高序列号。
SELECT COUNT(*) AS num, group_id, person_id, MAX(sequence)
FROM my_table
GROUP BY group_id, person_id
HAVING COUNT(*) > 1;
我确定我遗漏了一些简单的东西。有没有简单的方法来删除这些重复项?
谢谢。
所有列都应重复。所以按这样分组应用所有列
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);
尝试编写一个查询,return包含您要删除的行。假设 (group_id,person_id,sequence)
的组合是唯一的,并且您没有 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
我们可以将 SELECT
关键字替换为 DELETE
关键字,从而将其转换为 DELETE
语句。
或者,当我使用与此类似的语句删除行时,我通常会创建一个 table 作为我要删除的行的 "backup"。
在 SELECT 之前加上 CREATE TABLE some_new_table_name AS
。
然后,我们可以在 DELETE 查询中引用 "saved" 行
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
这种方法只能获得 "one" 的重复项。如果原始查询的计数值大于 2,那么我们需要重复此操作足够多次,每次删除最高序列值,重复直到没有大于 1 的计数值。
如果有很多重复项要删除,我们可以使用稍微不同的模式来一次性删除它们。
而不是 returning MAX(sequence)
(我们要删除的行),我们可以 return MIN(sequence)
,我们要保留的行。我们会改变谓词,
AND d.max_sequence = t.sequence
成为
AND d.min_sequence <> t.sequence
因此我们删除 所有 行 group_id, person_id
除了具有最小值的行。
我强烈建议您先将其写成 SELECT
,然后再将其转换为 DELETE
语句。我还建议您对要删除的行的 table and/or "save" 副本进行良好备份。以防万一您需要恢复一些行。