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


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

Ответы:



88
DELETE t1 
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID;

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

DELETE Table1 

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


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.
Стивен Меса


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

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

     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 некорректно завершена.


См. Этот ответ на другой вопрос для примера того, как написать удаление с соединением в 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');

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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.