Удалить строки SQL, где идентификаторы не совпадают из другой таблицы

161

Я пытаюсь удалить потерянные записи в таблице MySQL.

У меня есть 2 таблицы, как это:

Таблица files:

| id | ....
------------
| 1  | ....
| 2  | ....
| 7  | ....
| 9  | ....

стол blob:

| fileid | ....
------------
| 1  | ....
| 2  | ....
| 3  | ....
| 4  | ....
| 4  | ....
| 4  | ....
| 9  | ....

fileidИ idстолбцы могут быть использованы для объединения таблиц вместе.

Я хочу , чтобы удалить все строки в таблице , blobгде fileidне могут быть найдены в таблице files.id.

Поэтому, используя приведенный выше пример, мы удалили строки: 3 и 4 в blobтаблице.

Мартин
источник
1
Перейдите ко второму ответу, если вы используете nulls.
Pacerier

Ответы:

328

Использование LEFT JOIN / IS NULL:

DELETE b FROM BLOB b 
  LEFT JOIN FILES f ON f.id = b.fileid 
      WHERE f.id IS NULL

Использование НЕ СУЩЕСТВУЕТ:

DELETE FROM BLOB 
 WHERE NOT EXISTS(SELECT NULL
                    FROM FILES f
                   WHERE f.id = fileid)

Использование NOT IN:

DELETE FROM BLOB
 WHERE fileid NOT IN (SELECT f.id 
                        FROM FILES f)

Предупреждение

По возможности выполняйте УДАЛЕНИЯ внутри транзакции (при условии, что поддерживается - IE: не в MyISAM), чтобы вы могли использовать откат для отмены изменений в случае возникновения проблем.

OMG пони
источник
12
что вообще самое быстрое из вышеперечисленного?
Hampus Brynolf
2
По какой-то причине удаление с помощью LEFT JOIN не работало в MS SQL Server Mgmt Studio (не знаю почему; просто жаловалось на LEFT JOIN). Кто-нибудь знает, почему это? Это работало, используя НЕ СУЩЕСТВУЕТ, хотя :)
Анна
5
К вашему сведению, вот полезная дискуссия об относительной эффективности этих трех методов: объяснение
xix.com.
2
@Pacerier - "неправильно" немного сильно. Для того, чтобы убедиться , что люди понимают, что ответы делают работу , если fileidэто не-обнуляемым . Кроме того, третье решение ( NOT IN) требует только, чтобы это f.idне обнулялось. Предположительно, это первичный ключ, так и будет.
ToolmakerSteve
2
Для людей, пытающихся это сделать с помощью SQLite: посмотрите этот ответ
bunkerdive
26
DELETE FROM blob 
WHERE fileid NOT IN 
       (SELECT id 
        FROM files 
        WHERE id is NOT NULL/*This line is unlikely to be needed 
                               but using NOT IN...*/
      )
Мартин Смит
источник
Что такое "/ * эта строка вряд ли понадобится, но использование NOT IN ... * /" должно означать?
Pacerier
1
@Pacerier - NOT IN (NULL)возвращает пустой набор результатов, поэтому значения NULL должны быть исключены. Но idколонка, вероятно, в любом случае не будет обнуляемой, поэтому «вряд ли понадобится»
Мартин Смит
Вау, хороший улов. Так что ответ омгпонами неправильный! not in(null)довольно логично, почему не работает? Что за этим стоит?
Пейсер
1
@bunkerdive Затем используйте имена объектов из трех частей, которые включают имя базы данных.
Мартин Смит
18
DELETE FROM blob
WHERE NOT EXISTS (
    SELECT *
    FROM files
    WHERE id=blob.id
)
Джордж
источник
1
Я думаю, что есть files.idи blob.fileid. Я предполагаю, что ваш запрос приведет к ошибке.
jww
-9
delete from table1 t1 
    WHERE not exists (select id from table2 where related_field_in_t2=t1.id) 
    AND not exists (select id from table3 where related_field_in_t3=t1.id) 
    AND not exists (select id from table4 where related_field_t4=t1.id) 
    AND not exists (select id from table5 where related_field_t5=t1.id);
Камруджаман Хан
источник
3
Я понизил, потому что: 1. Это не пытается ответить на вопрос в контексте, который был опубликован. 2. Объяснения нет (и ответы только на код имеют низкое значение в Stackoverflow). 3. NOT EXISTSбыла опубликована 9 лет назад. 4. Вы не продвинули лучшую практику последовательного использования заглавных букв для ключевых слов MySQL. Другими словами, здесь ничего не стоит хранить, поэтому я также проголосовал за удаление этого поста.
mickmackusa