Удалить повторяющиеся строки, оставляя только самую старую строку?

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

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

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

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

Ответы

Ответ 1

Поскольку вы используете столбец 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' aliased x содержать только записи, соответствующие сообщениям электронной почты, но имеющие более высокое значение id. Данные, которые вы действительно хотите в таблице, уникальные адреса электронной почты (с наименьшим идентификатором) не будут частью x и не будут удалены. Единственными записями в x будут двойные записи (адреса электронной почты), у которых более высокий id, чем исходная запись для этого адреса электронной почты.

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

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

Чтобы предотвратить дубликаты, подумайте о том, чтобы сделать столбец subscriptionAndmail индексированным столбцом UNIQUE.

Ответ 2

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

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

Ответ 3

Если у вас есть уникальный идентификатор для каждой строки, вы можете попробовать что-то вроде этого. Не спрашивайте меня, почему именно вам нужен второй оператор 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
);