Usuń wiersze, do których nie odwołuje się inna tabela

15

Mam dwie tabele w bazie danych PostgreSQL 9.3: Tabela link_replyma klucz obcy o nazwie which_groupskierowanej do tabeli link_group.

Chcę usunąć wszystkie wiersze, z link_groupktórych nie link_replyistnieje żaden powiązany wiersz . Brzmi dość prosto, ale walczyłem z tym.

Czy będzie to coś takiego prostego (nie działa)?

DELETE FROM link_group WHERE link_reply = NULL;
Hassan Baig
źródło
czy masz DDL, na który wszyscy mogą patrzeć?
dizzystar
Spójrz na operatora MINUS. Musisz podać pole w 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
Mihai,
Miałem podobne pytanie, które uwzględnia również współbieżność. Zobacz dba.stackexchange.com/questions/251875 .
pbillen

Odpowiedzi:

19

Cytując instrukcję:

Istnieją dwa sposoby usuwania wierszy w tabeli przy użyciu informacji zawartych w innych tabelach w bazie danych: użycie podselekcji lub określenie dodatkowych tabel w USINGklauzuli . To, która technika jest bardziej odpowiednia, zależy od konkretnych okoliczności.

Odważny nacisk moje. Korzystanie z informacji, które nie są zawarte w innej tabeli, jest nieco trudne, ale istnieją proste rozwiązania. Od arsenału standardowych technik po ...

... NOT EXISTSanty-semi-join jest prawdopodobnie najprostszy i najbardziej wydajny dla DELETE:

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

Zakładając (ponieważ nie podano definicji tabeli) link_group_idjako nazwę kolumny dla klucza podstawowego link_group.

Technika skomentowana przez @Mihai również działa (stosowana poprawnie):

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;

Ale ponieważ wyrażenie tabeli w USINGklauzuli jest połączone z tabelą docelową ( lgw tym przykładzie) za pomocą a CROSS JOIN, potrzebujesz innej instancji tej samej tabeli jako odskocznia ( lg1w tym przykładzie) dla LEFT JOIN, która jest mniej elegancka i zazwyczaj wolniejsza.

Erwin Brandstetter
źródło