如何保留表格中的唯一一行,删除重复行?

23

我有一个表格,在Name列中有很多重复的记录。我想只保留每个记录中的一行。

以下列出了重复的行,但我不知道如何删除重复项并只保留一个:

SELECT name FROM members GROUP BY name HAVING COUNT(*) > 1;

谢谢。


10个回答

58

请查看以下问题:删除表中的重复行

从那里适应的被接受的答案(这是我的答案,所以这里没有“盗窃”...):

假设您有一个唯一的ID字段,您可以简单地执行以下操作:删除除了ID之外完全相同但不具有其名称的“最小ID”的所有记录。

示例查询:

DELETE FROM members
WHERE ID NOT IN
(
    SELECT MIN(ID)
    FROM members
    GROUP BY name
)

如果您没有唯一索引,我的建议是简单地添加一个自增的唯一索引。主要是因为这是良好的设计,也因为它将允许您运行上面的查询。


1
这是我的理解:对于每个名称,它将它们分组(如果唯一则只有一个;如果重复则合并为一个),从集合中选择最小的ID,然后删除任何ID不存在于表中的行。太棒了 :) 非常感谢 Rax。 - Gulbahar
2
在MySQL中,当我发送此查询时,出现以下错误:“错误1093(HY000)但它给出了一个错误'You cant specify target table 'members' for update in FROM clause”,有什么想法吗? - David LeBauer
1
问题在于“members”既是字段名又是表名。以下是可行的解决方法:删除不在(选择名称分组后最小ID的子查询中)的ID,即执行以下语句:delete from members where id not in (select min(id) from (select * from members) as x group by name)。 - David LeBauer
1
谢谢。你让我的一天变得美好。 - Priya Jagtap
我们可以执行以下SQL查询语句:DELETE FROM members WHERE ID NOT IN (SELECT name FROM members GROUP BY name HAVING COUNT(*) > 1;) - mach2
如果行完全相同,可以使用ROWID(而不是name)来区分行。 - xamgore

4

将唯一的数据选入一个新表中,删除旧表,然后将临时表重命名以替换旧表可能更容易。

#create a table with same schema as members
CREATE TABLE tmp (...);

#insert the unique records
INSERT INTO tmp SELECT * FROM members GROUP BY name;

#swap it in
RENAME TABLE members TO members_old, tmp TO members;

#drop the old one
DROP TABLE members_old;

1
感谢Paul。对于那些感兴趣的人...创建临时表tmp_members(name VARCHAR);从members中选择name并通过name进行分组,然后将其插入到tmp_members中;从tmp_members计算名字数量;从members中删除数据; 清空members; 再次从members计算名字数量;从tmp_members中选择并插入到members中; 从members计算名字数量; 从members计算不同名字的个数; 从members中选择前10个名字;删除表tmp_members; - Gulbahar
抱歉,我错过了你在使用SQLite! - Paul Dixon

0

如果我们想要先查看即将删除的行,然后再删除它们。

with MYCTE as (
    SELECT DuplicateKey1
        ,DuplicateKey2 --optional
        ,count(*) X
    FROM MyTable
    group by DuplicateKey1, DuplicateKey2
    having count(*) > 1
) 
SELECT E.*
FROM MyTable E
JOIN MYCTE cte
ON E.DuplicateKey1=cte.DuplicateKey1
    AND E.DuplicateKey2=cte.DuplicateKey2
ORDER BY E.DuplicateKey1, E.DuplicateKey2, CreatedAt

完整示例请参见 http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/


0

显示记录

SELECT `page_url`,count(*) FROM wl_meta_tags GROUP BY page_url HAVING count(*) > 1

删除记录

DELETE FROM wl_meta_tags 
WHERE meta_id NOT IN( SELECT meta_id 
FROM ( SELECT MIN(meta_id)AS meta_id FROM wl_meta_tags GROUP BY page_url HAVING COUNT(*) > 1 )AS a ) 
AND meta_id NOT IN( (SELECT ids FROM (
SELECT MIN(meta_id)AS ids FROM wl_meta_tags GROUP BY page_url HAVING COUNT(*) =1 )AS a1 ) )

源网址


0

你可以通过匹配字段将表与自身连接,并删除不匹配的行。

DELETE t1 FROM table_name t1 
LEFT JOIN tablename t2 ON t1.match_field = t2.match_field
WHERE t1.id <> t2.id;

0

我们有一个庞大的数据库,删除重复数据是常规维护过程的一部分。我们使用DISTINCT选择唯一记录,然后将它们写入TEMPORARY TABLE。在TRUNCATE之后,我们将TEMPORARY数据写回TABLE。

这是一种方法,可以作为STORED PROCEDURE运行。


1
我不得不承认Rax Olgud的答案要高级得多,而且可能运行速度快100倍!:) - 我正在考虑采用这个解决方案... 值得+1! - G Berdal

0
从tablename表中删除 WHERE ID IN( SELECT MAX(ID) ID FROM tablename GROUP BY IDNumber HAVING COUNT(IDNumber) > 1 )

0

删除重复行但保留一行 表中存在重复行,可能有些行没有重复行,则保留一个行,如果表中有重复或单个行。 表格有两列id和name,如果我们需要从表格中删除重复的name并保留一个。在我的端口上运行良好,您可以使用此查询。

DELETE FROM tablename
WHERE id NOT IN(

 SELECT id FROM
(
    SELECT MIN(id)AS id
    FROM tablename
    GROUP BY name HAVING 
    COUNT(*) > 1
)AS a )
AND id NOT IN(
(SELECT ids FROM
(
SELECT MIN(id)AS ids
    FROM tablename
    GROUP BY name HAVING 
    COUNT(*) =1
)AS a1
)
)

在删除表之前,请参见以下截图: 输入图像描述 在删除表之后,下面是包含此查询的截图,该查询将删除Amit和Akhil的重复行并保留一条记录(Amit和Akhil):

输入图像描述


0

如果你想从表中删除重复记录。

CREATE TABLE tmp SELECT lastname, firstname, sex
FROM user_tbl;
GROUP BY (lastname, firstname);

DROP TABLE user_tbl;

ALTER TABLE tmp RENAME TO user_tbl;

-1
WITH CTE AS
(
    SELECT ROW_NUMBER() OVER (PARTITION BY [emp_id] ORDER BY [emp_id]) AS Row, * FROM employee_salary
)


DELETE FROM CTE
WHERE ROW <> 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接