結合されていないレコードを見つけるにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/151099

  •  02-07-2019
  •  | 
  •  

質問

結合された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られた:)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top