web-dev-qa-db-ja.com

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

2つのテーブルが結合されています。

Aには多くのBがあります

通常は次のようにします:

select * from a,b where b.a_id = a.id

Bにレコードがあるaからすべてのレコードを取得する。

Bに何もないaのレコードだけを取得するにはどうすればよいですか?

45
Sixty4Bit
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
77
albertein
select * from a
left outer join b on a.id = b.a_id
where b.a_id is null
17
Joseph Anderson

別のアプローチ:

select * from a where not exists (select * from b where b.a_id = a.id)

「exists」アプローチは、内部クエリにアタッチする必要がある他の「where」句がある場合に役立ちます。

5
Matt Hamilton
SELECT id FROM a
EXCEPT
SELECT a_id FROM b;
4
onedaywhen
SELECT <columnns>
FROM a WHERE id NOT IN (SELECT a_id FROM b)
1
BlackWasp

外部結合を使用すると、おそらく( 'not in'を使用するよりも)はるかに優れたパフォーマンスが得られます。

select * from a left outer join b on a.id = b.a_id where b.a_id is null;
1
nathan

1つの結合の場合はかなり高速ですが、約5,000万のレコードと外部キーによる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)

カスケード削除を構成していない場合に備えて、この削除方法もお勧めします。このクエリは数秒しかかかりません。

0
Petr Štipek

それを書く別の方法

select a.*
from a 
left outer join b
on a.id = b.id
where b.id is null

痛い、ネイサンに殴られた:)

0
shahkalpesh

これにより、IN句のnullから保護され、予期しない動作を引き起こす可能性があります。

select * from a where id not in(select [a id] from b where [a id] is not null

0
Amy B

最初のアプローチは

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分後に終了していません。

0
Daniele Licitra