結合されていないレコードを見つけるにはどうすればよいですか?
質問
結合された2つのテーブルがあります。
Aには多くのBがあります
通常は次のようにします:
select * from a,b where b.a_id = a.id
bにレコードがあるaからすべてのレコードを取得するには。
bに何も含まれていないaのレコードだけを取得するにはどうすればよいですか?
解決
select * from a where id not in (select a_id from b)
またはこのスレッドの他の人が言うように:
select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null
他のヒント
select * from a
left outer join b on a.id = b.a_id
where b.a_id is null
別のアプローチ:
select * from a where not exists (select * from b where b.a_id = a.id)
「存在する」他の「場所」がある場合、アプローチは便利です。内部クエリに添付する必要がある句。
SELECT id FROM a
EXCEPT
SELECT a_id FROM b;
select * in where where id not in(select a_id from b)
外部結合を使用すると、おそらく「not in」を使用するよりもはるかに優れたパフォーマンスが得られます。
select * from a left outer join b on a.id = b.a_id where b.a_id is null;
これにより、IN句のnullから保護され、予期しない動作が発生する可能性があります。
select * a where id not in( [a id]がnullではないbから[a id]を選択)
1つの結合の場合、それは非常に高速ですが、約50百万レコードと外部キーによる4つ以上の結合を持つデータベースからレコードを削除する場合、それを行うには数分かかります。 次のようなWHERE NOT IN条件を使用する方がはるかに高速です:
select a.* from a
where a.id NOT IN(SELECT DISTINCT a_id FROM b where a_id IS NOT NULL)
//And for more joins
AND a.id NOT IN(SELECT DISTINCT a_id FROM c where a_id IS NOT NULL)
カスケード削除を設定していない場合は、このアプローチを削除することをお勧めします。 このクエリには数秒しかかかりません。
最初のアプローチは
ですselect a.* from a where a.id not in (select b.ida from b)
2番目のアプローチは
select a.*
from a left outer join b on a.id = b.ida
where b.ida is null
最初のアプローチは非常に高価です。 2番目のアプローチの方が優れています。
PostgreSql 9.4で、「クエリの説明」を行いました。関数とコストとしての最初のクエリ cost = 0.00..1982043603.32 。 代わりに、 cost = 45946.77..45946.78
のコストとしての結合クエリたとえば、車と互換性がないすべての製品を検索します。 10万の製品と100万を超える互換性を持っています。
select count(*) from product a left outer join compatible c on a.id=c.idprod where c.idprod is null
結合クエリは約5秒かかりましたが、代わりにサブクエリバージョンは3分後に終了していません。
別の書き方
select a.*
from a
left outer join b
on a.id = b.id
where b.id is null
痛い、ネイサンにbeatられた:)