УДАЛИТЬ строки, на которые нет ссылок в другой таблице

15

У меня есть две таблицы в базе данных PostgreSQL 9.3: Таблица link_replyимеет внешний ключ, which_groupуказывающий на таблицу link_group.

Я хочу удалить все строки, из link_groupкоторых не существует связанных строк link_reply. Звучит достаточно просто, но я боролся с этим.

Будет ли что-то простое, как это (не работает)?

DELETE FROM link_group WHERE link_reply = NULL;
Хасан Бэйг
источник
у вас есть DDL для всех, чтобы посмотреть?
dizzystar
Посмотрите на оператора МИНУС. Вы должны указать поле в links_reply.
Vérace
DELETE FROM links_group USING links_group AS lg LEFT JOIN links_reply AS lr ON lg.col= lr.some_other_col WHERE links_reply.some_other_col IS NULL
Михай
У меня был похожий вопрос, который также учитывает параллелизм. См. Dba.stackexchange.com/questions/251875 .
pbillen

Ответы:

19

Цитирование руководства:

Существует два способа удаления строк в таблице с использованием информации, содержащейся в других таблицах в базе данных: использование вложенных выборок или указание дополнительных таблиц в USINGпредложении . Какой метод больше подходит, зависит от конкретных обстоятельств.

Жирный акцент мой. Использование информации, которая не содержится в другой таблице, немного сложно, но есть простые решения. От арсенала стандартных приемов до ...

... NOT EXISTSанти-полусоединение, вероятно, самое простое и наиболее эффективное для DELETE:

DELETE FROM link_group lg
WHERE  NOT EXISTS (
   SELECT FROM link_reply lr
   WHERE  lr.which_group = lg.link_group_id
   );

Предполагая (поскольку определения таблиц не предоставлены) в link_group_idкачестве имени столбца для первичного ключа link_group.

Техника @Mihai прокомментировала также хорошо (применяется правильно):

DELETE FROM link_group lg
USING  link_group      lg1
LEFT   JOIN link_reply lr ON lr.which_group = lg1.link_group_id
WHERE  lg1.link_group_id = lg.link_group_id
AND    lr.which_group IS NULL;

Но поскольку табличное выражение в USINGпредложении объединено с целевой таблицей ( lgв примере) с помощью a CROSS JOIN, вам необходим другой экземпляр той же таблицы в качестве ступеньки ( lg1в примере) для объекта LEFT JOIN, который менее элегантен и обычно медленнее.

Эрвин Брандштеттер
источник