Find most recent duplicates ID with MySQL

2020-04-06 03:00发布

I use to do

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

to find duplicates based on their email.

But now I'd need their ID to be able to define which one to remove exactly.

The second constraint is: I want only the LAST INSERTED duplicates.

So if there's 2 entries with test@test.com as an email and their IDs are respectively 40 and 12782 it would delete only the 12782 entry and keep the 40 one.

Any ideas on how I could do this? I've been mashing SQL for about a hour and can't seem to find exactly how to do this.

Thanks and have a nice day!

5条回答
男人必须洒脱
2楼-- · 2020-04-06 03:45
DELETE duplicates.*
FROM wineries
JOIN wineries AS duplicates USING (email)
WHERE duplicates.id < wineries.id;

play with it on sqlfiddle.com

查看更多
来,给爷笑一个
3楼-- · 2020-04-06 03:48

This is the simplest option:

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

This will only keep the first inserted record for each email address, all other records will be deleted. Credit for this answer should go to @juergen d since this is just a revised version of his answer.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2020-04-06 03:58
delete from wineries
where id not in
(
  select * from 
  ( 
     select min(id)
     from wineries
     group by email
  ) x
)

You need a subquery to trick MySQL to delete from a table it is selecting from at the same time.

查看更多
等我变得足够好
5楼-- · 2020-04-06 03:59
select email, max(id), COUNT(email) AS occurences
FROM wineries
GROUP BY email
HAVING (COUNT(email) > 1);
查看更多
干净又极端
6楼-- · 2020-04-06 04:04

Well, you sort of answer your question. You seem to want max(id):

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

You can delete the others using the statement. Delete with join has a tricky syntax where you have to list the table name first and then specify the from clause with the join:

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;

Or writing this as an exists clause:

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
                 )
查看更多
登录 后发表回答