Найти самые последние дубликаты ID с помощью MySQL

я использую, чтобы делать

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

чтобы найти дубликаты на основе их электронной почты.

Но теперь мне нужен их идентификатор, чтобы определить, какой именно удалить.

Второе ограничение: мне нужны только ПОСЛЕДНИЕ ВСТАВЛЕННЫЕ дубликаты.

Таким образом, если есть 2 записи с адресом электронной почты [email protected] и их идентификаторы соответственно 40 и 12782, будет удалена только запись 12782 и сохранена запись 40.

Любые идеи о том, как я могу это сделать? Я месил SQL около часа и не могу найти, как именно это сделать.

Спасибо, и хорошего дня!


person Tommy B.    schedule 12.07.2013    source источник
comment
Является ли идентификатор числовым и упорядоченным? Всегда ли запись 231 следует за записью 32?   -  person Brian Hoover    schedule 12.07.2013
comment
Хороший вопрос: да. Спасибо за вопрос!   -  person Tommy B.    schedule 12.07.2013


Ответы (5)


Ну вы как бы ответили на свой вопрос. Кажется, вы хотите 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
                 )
person Gordon Linoff    schedule 12.07.2013
comment
Первый: 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, для правильного синтаксиса для использования рядом с «w join» (выберите адрес электронной почты, max (winery_id) как maxid из группы виноделен по электронной почте, имеющейся в строке 10 - person Tommy B.; 12.07.2013
comment
Второй: 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) дает мне: Неизвестный столбец «we.winery_id» в «где пункт» - person Tommy B.; 12.07.2013
comment
Спасибо за ответ и за предложение более чем одного решения. - person Tommy B.; 12.07.2013
comment
Я также забыл упомянуть, что электронная почта НЕ должна быть нулевой. Потому что ноль проходит как дубликат, и все те, у которых НЕТ электронной почты, удаляются. Могу ли я просто добавить WHERE email IS NOT NULL между винодельнями from и группой by? - person Tommy B.; 12.07.2013

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

Вам нужен подзапрос, чтобы обмануть MySQL, чтобы удалить из таблицы, из которой он выбирает в то же время.

person juergen d    schedule 12.07.2013
comment
Что делать, если запись НЕ имеет дубликатов? будут ли они удалены, так как запрос их не получит? О, я думаю, что группа по-прежнему будет получать ту, у которой нечего сгруппировать? - person Tommy B.; 12.07.2013
comment
Нет, так как вы выбираете самые низкие идентификаторы и не удаляете их (where id not in) - записи без дубликатов сохраняются. - person juergen d; 12.07.2013
comment
Делаем так: select * from wineries where winery_id not in ( select * from ( select min(winery_id) from wineries group by email ) x ) чтобы проверить, что будет удалено, на самом деле дал мне список последних, а не последних. Это нормально? - person Tommy B.; 12.07.2013
comment
Вы уверены, что у вас есть последние записи с этим запросом? min(id) получит самый низкий id. - person juergen d; 12.07.2013
comment
Он удаляет идентификаторы, которых нет в этом списке. Так что это удалит ВСЕ идентификаторы, которые не являются первым идентификатором, найденным для любого электронного письма. Подзапрос уровня select * from в этом случае не нужен, и его псевдоним вызовет здесь ошибку. - person drakin8564; 05.04.2019

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

поэкспериментируйте с ним на sqlfiddle.com

person RandomSeed    schedule 12.07.2013
comment
ОП хочет удалить самые новые введенные идентификаторы и сохранить первый. Этот ответ сохранит только самый новый идентификатор. - person drakin8564; 05.04.2019

Это самый простой вариант:

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

Это сохранит только первую вставленную запись для каждого адреса электронной почты, все остальные записи будут удалены. Кредит за этот ответ должен быть передан @juergen d, так как это всего лишь исправленная версия его ответа.

person drakin8564    schedule 05.04.2019

person    schedule
comment
Это удалит только самый последний вставленный идентификатор, в котором есть дубликаты. если есть 3+ записи с одним и тем же адресом электронной почты, у него все равно будут дубликаты. - person drakin8564; 05.04.2019