Удалить повторяющиеся строки, оставив только самый старый ряд? - PullRequest
13 голосов
/ 09 сентября 2010

У меня есть таблица данных, и есть много повторяющихся записей из пользовательских представлений.

Я хочу удалить все дублирующиеся строки на основе поля subscriberEmail, оставив только исходную отправку.

Другими словами, я хочу найти все повторяющиеся электронные письма и удалить эти строки, оставив только оригинал.

Как я могу сделать это без обмена таблицами?
Моя таблица содержит уникальные идентификаторы для каждой строки.

Ответы [ 3 ]

27 голосов
/ 09 сентября 2010

Поскольку вы используете столбец id в качестве индикатора того, какая запись является «оригинальной»:

delete x 
from myTable x
 join myTable z on x.subscriberEmail = z.subscriberEmail
where x.id > z.id

Это оставит одну запись на адрес электронной почты.

изменить, чтобы добавить:

Чтобы объяснить запрос выше ...

Идея в том, чтобы присоединиться к столу против себя. Представьте, что у вас есть две копии таблицы, каждая из которых имеет свое имя. Затем вы можете сравнить их друг с другом и найти самый низкий идентификатор или для каждого адреса электронной почты. Затем вы увидите дубликаты записей, которые были созданы позже, и сможете их удалить. (Я думал о Excel, когда думал об этом.)

Чтобы выполнить эту операцию над таблицей, сравнить ее с самим собой и иметь возможность идентифицировать каждую сторону, вы используете псевдонимы таблицы. x - псевдоним таблицы. Он назначается в предложении from следующим образом: from <table> <alias>. x теперь можно использовать в другом месте того же запроса, чтобы ссылаться на эту таблицу как на ярлык.

delete x начинает запрос с нашего действия и цели. Мы собираемся выполнить запрос, чтобы выбрать записи из нескольких таблиц, и мы хотим удалить записи, которые появляются в x.

Псевдонимы используются для ссылки на оба «экземпляра» таблицы. from myTable x join myTable z on x.subscriberEmail = z.subscriberEmail поднимает таблицу против себя, где совпадают электронные письма. Без последующего предложения where каждая запись будет выбрана, поскольку она может быть объединена с самим собой.

Предложение where ограничивает выбранные записи. where x.id > z.id позволяет псевдониму "instance" x содержать только записи, которые соответствуют адресам электронной почты, но имеют более высокое значение id. Данные, которые вам действительно нужны в таблице, уникальные адреса электронной почты (с наименьшим идентификатором) не будут частью x и не будут удалены. Единственными записями в x будут повторяющиеся записи (адреса электронной почты), которые имеют id выше, чем исходная запись для этого адреса электронной почты.

В этом случае можно объединить предложения join и where:

delete x 
  from myTable x 
  join myTable z
    on x.subscriberEmail = z.subscriberEmail
      and x.id > z.id

Для предотвращения дублирования рассмотрите возможность сделать столбец subscriberEmail уникальным индексированным столбцом.

1 голос
/ 11 июля 2013

Как насчет этого, теперь вам не нужно создавать временные таблицы, используя самостоятельные объединения

DELETE u1 FROM users u1, users u2 WHERE u1.id < u2.id AND u1.email = u2.email

Чтобы проверить, есть ли дубликаты записей в таблице

SELECT count(*) as Count, email FROM users u group by email having Count > 1
0 голосов
/ 09 сентября 2010

Если у вас есть уникальный идентификатор для каждой строки, вы можете попробовать что-то вроде этого. Не спрашивайте меня, почему именно вам нужен второй оператор select, mysql не позволит мне выполнить иначе. Кроме того, группируйте по тем столбцам, которые делают ваши результаты уникальными.

delete from my_table where id in (
  select id from (
    select id from my_table a group by subscriberEmail having count(*) > 1
  ) b
);
...