Видалити всі рядки таблиці на основі іншої таблиці


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, оскільки це запобігає випадковому

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';

Видалення записів із об’єднанням також можна виконати за допомогою ЛІВОГО ПРИЄДНАННЯ та КУДИ, щоб перевірити, чи є об’єднана таблиця НУЛЬКОЮ, щоб можна було видалити записи в одній таблиці, які не мають збігу (наприклад, під час підготовки до додавання зв’язку. ) Приклад поштового повідомлення.


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 неправильно закінчилася.


Див. Цю відповідь на інше запитання для прикладу того, як написати видалення за допомогою join під Oracle.
Фредерік,

0

Хоча ОП не хоче використовувати оператор "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.