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


15

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

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

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

DELETE FROM link_group WHERE link_reply = NULL;

誰もが見ることができるDDLはありますか?
dizzystar 2016

MINUS演算子を見てください。あなたは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

同様の質問がありましたが、これも同時実行性を考慮に入れています。dba.stackexchange.com/questions/251875を参照してください。
pbillen

回答:


19

マニュアルの引用:

データベース内の他のテーブルに含まれている情報を使用してテーブル内の行を削除する方法は2つあります。副選択を使用する方法と、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例の)ターゲットテーブルにで結合されているため、のCROSS JOIN飛び石(lg1例の)と同じテーブルの別のインスタンスが必要LEFT JOINです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.