web-dev-qa-db-ja.com

他のテーブルで参照されていない行を削除する

PostgreSQL 9.3データベースに2つのテーブルがあります。テーブルlink_replyには、テーブルwhich_groupを指すlink_groupという名前の外部キーがあります。

link_groupに関連する行が存在しないlink_replyからすべての行を削除したい。基本的には十分に聞こえますが、私はそれに苦労しています。

これはこのような単純なものになりますか(機能しません)?

DELETE FROM link_group WHERE link_reply = NULL;
15
Hassan Baig

マニュアルの引用:

データベース内の他のテーブルに含まれている情報を使用してテーブル内の行を削除するには、副選択を使用する方法と、USING句で追加のテーブルを指定する方法の2つがあります。どの手法がより適切であるかは、特定の状況によって異なります。

大胆な強調鉱山。別のテーブルに含まれているnotである情報を使用するのは少し厄介ですが、簡単な解決策があります。標準的な技術の武器庫から...

... 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_idlink_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句のテーブル式はCROSS JOINを使用してターゲットテーブル(例ではlg)に結合されているため、飛び石と同じテーブルの別のインスタンスが必要です。 (例ではlg1LEFT JOINの場合、エレガントさが低下し、通常は遅くなります。

19