MySQL запрос DELETE с условиями

У меня есть таблица PEOPLE со столбцами «firstName», «lastName» (varchars) и «deleted» (bit) среди прочих.

Я хочу удалить из этой таблицы записи, которые имеют свойство TRUE для удаления, но только если они разделяют свое точное имя и фамилию с другой, отдельной записью в таблице.

Другими словами, удалить из таблицы «удаленных» людей, но только если они являются дубликатами.

Не уверен, как это сделать, и особенно не знаю, как сделать это быстро. Любая помощь приветствуется, спасибо.


person Yottagray    schedule 27.06.2011    source источник
comment
Как определить, какая запись является дубликатом, а какая — первичной?   -  person AJ.    schedule 27.06.2011
comment
возможный дубликат Дубликаты записей в БД   -  person Naftali aka Neal    schedule 27.06.2011
comment
Все поля находятся в одной таблице?   -  person Antonio Laguna    schedule 27.06.2011
comment
@Antonio: все поля находятся в одной таблице   -  person Yottagray    schedule 27.06.2011


Ответы (3)


Если ваша таблица имеет уникальный первичный ключ (... будет зависеть от дизайна...), то это жизнеспособная альтернатива необходимости подсчета вхождений записей:

DELETE FROM people as A
WHERE deleted = 1
AND EXISTS (SELECT '1'
            FROM people as B
            WHERE B.id <> A.id
            AND A.firstName = B.firstName
            AND A.lastName = B.lastName)

Это может иметь немного лучшую производительность, чем подсчет строк. Обратите внимание, что этот запрос, вероятно, будет иметь ту же возможную проблему, что и в предыдущем ответе; в частности, если есть две или более «удаленных» строк и нет «неудаленных», обе они, вероятно, будут удалены (оставив вас без строк!). Если целью запроса является только удаление «удаленных» строк при наличии «неудаленной» эквивалентной строки, добавьте AND B.deleted = 0 как часть внутреннего предложения WHERE.

person Clockwork-Muse    schedule 27.06.2011
comment
Отлично - это позволяет легко AND B.deleted = 0 исправить то, что, как я подозреваю, хочет задающий вопросы, а другой - нет. - person Chris Cunningham; 28.06.2011
comment
Предложение: используйте A.id>B.id, чтобы все, что новее первой записи, было удалено. Также работает быстрее. - person niktrs; 28.06.2011
comment
@niktrs - К сожалению, это предполагает, что только более поздние (или более ранние) идентификаторы когда-либо «удаляются». В зависимости от дизайна и использования это предположение может быть или не быть действительным. Но да, в противном случае это, вероятно, работало бы лучше. - person Clockwork-Muse; 28.06.2011

Вот элементарный способ сделать это:

http://www.justin-cook.com/wp/2006/12/12/remove-duplicate-entries-rows-a-mysql-database-table/

В основном:
1. Создайте новую таблицу с GROUP BY.
2. Удалите старую таблицу.
3. Переименуйте новую таблицу.

person Naftali aka Neal    schedule 27.06.2011

person    schedule
comment
вам нужно предложение where во вложенном выражении? - person Dirk; 27.06.2011
comment
Да, чтобы присоединиться к подзапросу с внешней таблицей. - person niktrs; 27.06.2011
comment
@niktrs, это займет очень много времени, потому что стол огромен. - person Naftali aka Neal; 27.06.2011
comment
не удалит ли этот запрос все записи, которые удалили = 1? - person Abhay; 27.06.2011
comment
Нас спрашивают, я хочу удалить из этой таблицы записи, которые имеют свойство TRUE для удаления, но только если они разделяют свои точные имя и фамилию с другим, поэтому мы хотим, чтобы удалено = 1, и каждая фамилия, имя count > 1 - person niktrs; 27.06.2011
comment
@ Нил, возможно, ты прав насчет производительности. Я бы также посоветовал вам использовать DISTINCT, поскольку обычно он работает лучше, чем GROUP BY. - person niktrs; 27.06.2011
comment
@niktrs это занимает некоторое время, но, похоже, это работает. Спасибо - person Yottagray; 27.06.2011
comment
@Yottagray Возможные проблемы: во-первых, если в базе данных есть два разных человека по имени Джон Смит и одна из их записей помечена как удаленная, он исчез. Во-вторых, даже если у вас есть только один Джон Смит в базе данных, и у него есть две записи, но обе помечены как удаленные=1, то он удалит их обоих (не обязательно сохранит одну из них)! Может быть, это не важно для вас. - person Chris Cunningham; 28.06.2011
comment
@Chris Нет, мне важно это знать, я должен помнить об этом, когда буду работать дальше. Спасибо. - person Yottagray; 28.06.2011