Зняти рядки, на які не посилається інша таблиця


15

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

Я хочу видалити всі рядки з того місця, link_groupде не link_replyіснує жодного пов'язаного рядка . Звучить досить просто, але я з цим боровся.

Це буде щось просте на кшталт цього (не працює)?

DELETE FROM link_group WHERE link_reply = NULL;

у вас є DDL для всіх, хто їх може подивитися?
запаморочення

Погляньте на оператора MINUS. Ви повинні вказати поле у ​​link_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, який менш елегантний і, як правило, повільніше.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.