Удалить все строки в таблице на основе другой таблицы

81

Кажется, я не могу вспомнить этот запрос!

Я хочу удалить все строки в таблице 1, идентификаторы которых такие же, как в таблице 2.

Так:

DELETE table1 t1
 WHERE t1.ID = t2.ID

Я знаю, что могу сделать WHERE ID IN (SELECT ID FROM table2), но я хочу выполнить этот запрос, используя JOIN, если это возможно.

мрбла
источник
Почему вы хотите присоединиться?
tster
Что вы планируете делать с этим вопросом: stackoverflow.com/questions/1590709/…
OMG Ponies
Потому что соединения часто бывают быстрее.
HLGEM
@tster Возможно, это временная таблица идентификаторов, которую необходимо удалить
Стивен Меса
1
@HLGEM Вы говорите, что оптимизатор запросов недостаточно умен, чтобы выполнить простое «удаление из X, где XY IN (выберите Foo из панели)» так же быстро, как выполнение соединения? Я бы доверял оптимизатору, а не интуиции.
tster

Ответы:

87
DELETE Table1
FROM Table1
INNER JOIN Table2 ON Table1.ID = Table2.ID
Стивен Меса
источник
88
DELETE t1 
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID;

Я всегда использую псевдоним в операторе удаления, поскольку он предотвращает случайное

DELETE Table1 

возникает, когда не удается выделить весь запрос перед его запуском.

HLGEM
источник
5
Голосование в основном за комментарий «всегда использовать псевдоним». Отличная идея.
rosscova
35

В ANSI SQL нет решения использовать соединения при удалении, AFAIK.

DELETE FROM Table1
WHERE Table1.id IN (SELECT Table2.id FROM Table2)

Позже править

Другое решение (иногда работающее быстрее):

DELETE FROM Table1
WHERE EXISTS( SELECT 1 FROM Table2 Where Table1.id = Table2.id)
Кэтэлин Питиш
источник
В конце его вопроса говорится, что он хочет использовать соединение, а не предложение IN.
Стивен Меса
21

Реализация PostgreSQL будет:

DELETE FROM t1
USING t2
WHERE t1.id = t2.id;
Весанто
источник
4

Попробуй это:

DELETE Table1
FROM Table1 t1, Table2 t2
WHERE t1.ID = t2.ID;

или же

DELETE Table1
FROM Table1 t1 INNER JOIN Table2 t2 ON t1.ID = t2.ID;
Янник Моттон
источник
3

Я думаю, вы могли бы получить немного больше производительности, если бы попробовали это

DELETE FROM Table1
WHERE EXISTS (
  SELECT 1
  FROM Table2
  WHERE Table1.ID = Table2.ID
)
Богертрон
источник
3

Это приведет к удалению всех строк Table1, соответствующих критериям:

DELETE Table1 
FROM Table2 
WHERE Table1.JoinColumn = Table2.JoinColumn And Table1.SomeStuff = 'SomeStuff'
Больше
источник
2

Эта ссылка оказалась полезной

Скопировано оттуда

Часто нужно удалить некоторые записи из таблицы на основе критериев в другой таблице. Как удалить из одной из этих таблиц, не удаляя записи в обеих таблицах?

DELETE DeletingFromTable
     FROM DeletingFromTable INNER JOIN CriteriaTable
     ON DeletingFromTable.field_id = CriteriaTable.id
     WHERE CriteriaTable.criteria = "value";

Ключ в том, что вы указываете имя таблицы, из которой нужно удалить, как SELECT. Итак, JOIN и WHERE производят выбор и ограничение, а DELETE - удаление. Однако вы не ограничены одним столом. Если у вас есть отношение «многие ко многим» (например, журналы и подписчики, к которым присоединилась подписка), и вы удаляете подписчика, вам также необходимо удалить любые потенциальные записи из модели присоединения.

 DELETE subscribers, subscriptions
     FROM subscribers INNER JOIN subscriptions 
       ON subscribers.id = subscriptions.subscriber_id
     INNER JOIN magazines 
       ON subscriptions.magazine_id = magazines.id
     WHERE subscribers.name='Wes';

Удаление записей с помощью соединения также может быть выполнено с помощью LEFT JOIN и WHERE, чтобы увидеть, была ли объединенная таблица NULL, чтобы вы могли удалить записи в одной таблице, у которых не было совпадений (например, при подготовке к добавлению отношения. ) Пример сообщения будет позже.

Анкур Гупта
источник
2

Поскольку OP не запрашивает конкретную БД, лучше использовать стандартный совместимый оператор. Только MERGEв стандарте SQL для удаления (или обновления) строк при объединении чего-либо в целевой таблице.

merge table1 t1
    using (
        select t2.ID
            from table2 t2
    ) as d
    on t1.ID = d.ID
    when matched then delete;

MERGEимеет более строгую семантику, защищая от некоторых ошибок, которые могут остаться незамеченными DELETE ... FROM. Он обеспечивает «уникальность» совпадения: если многие строки в источнике (оператор внутри using) соответствуют одной и той же строке в целевом объекте, слияние должно быть отменено, и механизм SQL должен вызвать ошибку.

Фредерик
источник
это более чище, чем конструкция delete-join
asakura89
0

Ссылка на MSDN T-SQL DELETE (пример D):

DELETE FROM Table1
FROM Tabel1 t1
   INNER JOIN Table2 t2 on t1.ID = t2.ID
Остин Салонен
источник
0

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

     Delete From Table1 a,Table2 b where a.id=b.id

    Or

      DELETE FROM Table1
    WHERE Table1.id IN (SELECT Table2.id FROM Table2)

  Or

        DELETE Table1
     FROM Table1 t1 INNER JOIN Table2 t2 ON t1.ID = t2.ID;
Кавита Редди
источник
0

Я знаю, что это старое, но это просто указатель на всех, кто использует эту задницу как ссылку. Я только что пробовал это, и если вы используете Oracle, JOIN не работает в операторах DELETE. Вы получите следующее сообщение:

ORA-00933: Команда SQL некорректно завершена.

KS1
источник
См. Этот ответ на другой вопрос для примера того, как написать удаление с соединением в Oracle.
Frédéric
0

Хотя OP не хочет использовать оператор 'in', в ответ Анкуру Гупте это был самый простой способ, который я нашел, чтобы удалить записи в одной таблице, которых не было в другой таблице, в отношении один ко многим :

DELETE
FROM Table1 as t1
WHERE ID_Number NOT IN
(SELECT ID_Number FROM Table2 as t2)

Для меня Access 2016 отлично сработал.

Роб
источник
0

Я часто делаю такие вещи, как следующий выдуманный пример. (Этот пример взят из Informix SE, работающей в Linux.)

Смысл этого примера состоит в том, чтобы удалить все записи транзакций по освобождению / сокращению выбросов в отношении недвижимости - поскольку в приложении по борьбе с выбросами есть ошибка - на основе информации в таблице real_estate.

В этом случае last_update != nullозначает, что учетная запись не закрыта, и res_exempt != 'p'означает, что учетные записи не являются личной собственностью (торговое оборудование / мебель).

delete from trans 
where   yr = '16'
and     tran_date = '01/22/2016'
and     acct_type = 'r'
and     tran_type = 'a'
and     bill_no in
(select acct_no from real_estate where last_update is not null
 and res_exempt != 'p');

Мне нравится этот метод, потому что критерии фильтрации - по крайней мере для меня - легче читать при создании запроса и понимать через много месяцев, когда я смотрю на него и задаюсь вопросом, о чем я думал.

осьминогграббус
источник
0
delete
    table1
from 
    t2
where
    table1.ID=t2.ID

Работает на mssql

Кен Кин
источник