HAPUS baris yang tidak direferensikan di tabel lain

15

Saya memiliki dua tabel dalam database PostgreSQL 9.3: Tabel link_replymemiliki kunci asing bernama which_groupmenunjuk ke tabel link_group.

Saya ingin menghapus semua baris dari link_grouptempat tidak ada baris terkait link_reply. Kedengarannya cukup mendasar tetapi saya sudah berjuang dengan itu.

Apakah ini akan menjadi sesuatu yang sederhana seperti ini (tidak berfungsi)?

DELETE FROM link_group WHERE link_reply = NULL;
Hassan Baig
sumber
apakah Anda memiliki DDL untuk dilihat semua orang?
dizzystar
Lihatlah operator MINUS. Anda harus menentukan bidang di 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
Saya punya pertanyaan serupa, yang juga mempertimbangkan konkurensi. Lihat dba.stackexchange.com/questions/251875 .
pbillen

Jawaban:

19

Mengutip manual:

Ada dua cara untuk menghapus baris dalam tabel menggunakan informasi yang terkandung dalam tabel lain dalam database: menggunakan sub-seleksi, atau menentukan tabel tambahan dalam USINGklausa . Teknik mana yang lebih tepat tergantung pada keadaan spesifik.

Penekanan berani saya. Menggunakan informasi yang tidak terkandung dalam tabel lain agak sulit, tetapi ada solusi mudah. Dari gudang teknik standar untuk ...

... NOT EXISTSanti-semi-join mungkin paling sederhana dan paling efisien untuk DELETE:

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

Dengan asumsi (karena definisi tabel tidak disediakan) link_group_idsebagai nama kolom untuk kunci utama link_group.

Teknik @Mihai berkomentar juga bekerja (diterapkan dengan benar):

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;

Tetapi karena ekspresi tabel dalam USINGklausa digabungkan ke tabel target ( lgdalam contoh) dengan a CROSS JOIN, Anda perlu contoh lain dari tabel yang sama dengan batu loncatan ( lg1dalam contoh) untuk LEFT JOIN, yang kurang elegan dan biasanya lebih lambat.

Erwin Brandstetter
sumber