使用MySQL查找最近的重复ID

5
我曾经做过
SELECT email, COUNT(email) AS occurences
FROM wineries
GROUP BY email
HAVING (COUNT(email) > 1);

根据他们的电子邮件找到重复项。

但是现在我需要它们的ID才能确定要删除哪个。

第二个限制是:我只想要最后插入的重复项。

因此,如果有两个条目具有test@test.com作为电子邮件,并且它们的ID分别为40和12782,则仅删除12782条目并保留40条目。

你有任何想法吗?我已经在折腾SQL约一个小时了,似乎找不到如何做到这一点。

谢谢,祝您愉快!


1
ID是否为数字且顺序正确?记录231是否总是在记录32之后? - Brian Hoover
好问题:是的,谢谢你的提问! - Tommy B.
可能是(咳咳)http://stackoverflow.com/questions/17612918/mysql-delete-older-duplicates 的重复内容。 - RandomSeed
5个回答

6

很好,你似乎已经回答了自己的问题。你似乎想要max(id)

SELECT email, COUNT(email) AS occurences, max(id)
FROM wineries
GROUP BY email
HAVING (COUNT(email) > 1);

您可以使用该语句删除其他内容。使用join进行删除时,语法有些棘手,您需要首先列出表名,然后指定带有连接的from子句:
delete wineries
            from wineries join
            (select email, max(id) as maxid
             from wineries
             group by email
             having count(*) > 1
            ) we
            on we.email = wineries.email and
               wineries.id < we.maxid;

或者将其写为exists子句:

delete from wineries
    where exists (select 1
                  from (select email, max(id) as maxid
                        from wineries
                        group by email
                       ) we
                  where we.email = wineries.email and wineries.id < we.maxid
                 )

第一个:delete from wineries w join (select email, max(winery_id) as maxid from wineries group by email having count(*) > 1 ) we on we.email = w.email and we.winery_id < maxid; 给我返回的是:您的SQL语法有误,请检查与您的MySQL服务器版本相对应的手册,以获取正确的语法使用方法,在第10行附近。 - Tommy B.
第二个问题:delete from wineries where exists (select 1 from (select email, max(winery_id) as maxid from wineries group by email ) we where we.email = wineries.email and we.winery_id < maxid) 给出的错误信息是:在“where”子句中未知的列'we.winery_id'。 - Tommy B.
感谢您的回复和建议多种解决方案。 - Tommy B.
我还忘了提到,电子邮件地址不应为空。因为空值会被视为重复项,所有没有电子邮件地址的记录都将被删除。我能否在从葡萄酒厂开始和分组之间添加 WHERE email IS NOT NULL 来解决这个问题? - Tommy B.

1
select email, max(id), COUNT(email) AS occurences
FROM wineries
GROUP BY email
HAVING (COUNT(email) > 1);

这将仅删除最近插入的重复ID。如果有3个或更多记录具有相同的电子邮件,则仍将存在重复项。 - derek.wolfe

0

这是最简单的选项:

DELETE FROM wineries
 WHERE id NOT IN
(
  SELECT MIN(id) id
    FROM wineries
GROUP BY email 
);

这将仅保留每个电子邮件地址的第一个插入记录,所有其他记录将被删除。此答案的功劳应归于@juergen d,因为这只是他答案的修订版本。


0
delete from wineries
where id not in
(
  select * from 
  ( 
     select min(id)
     from wineries
     group by email
  ) x
)

你需要使用子查询来欺骗MySQL在同时从一个表中进行选择和删除。

如果一个条目没有重复项怎么办?它们会被删除吗,因为查询不会获取它们?哦,我猜group by仍然会获取那些没有可分组的内容的条目? - Tommy B.
不会,因为您选择了最低的ID并且没有删除它们(where id not in)- 没有重复项的条目是安全的。 - juergen d
执行以下操作:select * from wineries where winery_id not in ( select * from ( select min(winery_id) from wineries group by email ) x )以检查实际将被删除的内容,结果却给出了最近的列表而不是最新的列表。这正常吗? - Tommy B.
你确定使用该查询语句获取了最新的条目吗?min(id)将会获取最小的id - juergen d
他正在删除不在该列表中的ID。因此,这将删除任何电子邮件的第一个找到的ID之外的所有ID。在此情况下,不需要选择*来自级别子查询,并对其进行别名处理会导致错误。 - derek.wolfe

0
DELETE duplicates.*
FROM wineries
JOIN wineries AS duplicates USING (email)
WHERE duplicates.id < wineries.id;

在sqlfiddle.com上玩耍


OP想要删除最新输入的ID并保留第一个。这个答案只会保留最新插入的ID。 - derek.wolfe

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