【问题标题】:Find most recent duplicates ID with MySQL使用 MySQL 查找最近的重复 ID
【发布时间】:2013-07-11 04:52:04
【问题描述】:

我经常这样做

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

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

但现在我需要他们的 ID 才能定义要准确删除的 ID。

第二个限制是:我只想要 LAST INSERTED 重复项。

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

关于如何做到这一点的任何想法?我已经捣碎了大约一个小时的 SQL,但似乎找不到确切的方法。

谢谢,祝你有美好的一天!

【问题讨论】:

标签: mysql sql duplicates duplicate-removal


【解决方案1】:

嗯,你有点回答你的问题。你好像想要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(*) &gt; 1 ) we on we.email = w.email and we.winery_id &lt; maxid; 给我:你的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册以获取正确的语法,以便在第 10 行的“w join (select email, max(winery_id) as maxid from wineries group by email havin”附近使用
  • 第二个: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 &lt; maxid)给我:'where子句'中的未知列'we.winery_id'
  • 感谢您的回复并提出多个解决方案。
  • 我也忘了提一下,email 不应该为空。因为 null 作为副本传递,所有没有电子邮件的人都会被删除。我可以在 from wineries 和 group by 之间简单地添加一个WHERE email IS NOT NULL 吗?
【解决方案2】:
select email, max(id), COUNT(email) AS occurences
FROM wineries
GROUP BY email
HAVING (COUNT(email) > 1);

【讨论】:

  • 这只会删除最近插入的有重复的id。如果有 3 条以上的记录使用相同的电子邮件,他仍然会受到欺骗。
【解决方案3】:
delete from wineries
where id not in
(
  select * from 
  ( 
     select min(id)
     from wineries
     group by email
  ) x
)

你需要一个子查询来欺骗 MySQL 从它同时选择的表中删除。

【讨论】:

  • 如果一个条目没有重复项怎么办?由于查询不会得到它们,它们会被删除吗?哦,我猜 group by 仍然会获取没有可分组的那个?
  • 不,因为您选择了最低的 id 并且不删除它们 (where id not in) - 没有重复的条目将被保存。
  • 这样做:select * from wineries where winery_id not in ( select * from ( select min(winery_id) from wineries group by email ) x ) 检查将被删除的内容实际上给了我最近的列表而不是最新的列表。正常吗?
  • 您确定您获得了该查询的最新条目吗? min(id) 将获得最低的id
  • 他正在删除不在该列表中的 ID。因此,这将删除不是为任何电子邮件找到的第一个 id 的所有 id。这里不需要 select * from level 子查询,这里给它取别名会报错。
【解决方案4】:
DELETE duplicates.*
FROM wineries
JOIN wineries AS duplicates USING (email)
WHERE duplicates.id < wineries.id;

play with it on sqlfiddle.com

【讨论】:

  • OP 想要删除最新输入的 id 并保留第一个。此答案只会保留插入的最新 id。
【解决方案5】:

这是最简单的选择:

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

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

【讨论】:

    猜你喜欢
    • 2022-01-14
    • 1970-01-01
    • 2013-08-12
    • 2021-04-07
    • 1970-01-01
    • 2016-07-01
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多