web-dev-qa-db-ja.com

SQLの概念LEFT OUTER JOINとWHERE NOT EXISTSは基本的に同じですか?

WHERE NOT EXISTS (...)で始まるサブクエリではなく、LEFT OUTER JOINを使用することの違いは何ですか?

16
Steffan Harris

いいえ、それらはnotが最も単純なユースケースで同じ行セットを返すため、同じものではありません。

_LEFT OUTER JOIN_は、行が関連テーブルに存在する場合と存在しない場合の両方で、左側のテーブルからすべての行を返します。 WHERE NOT EXISTS()サブクエリは、関係が満たされていない行のみを返します。

ただし、_LEFT OUTER JOIN_を実行し、WHERE句の外部キー列で_IS NULL_を検索した場合、_WHERE NOT EXISTS_と同等の動作を行うことができます。

例えばこれは:

_SELECT 
  t_main.*
FROM 
   t_main
   LEFT OUTER JOIN t_related ON t_main.id = t_related.id
/* IS NULL in the WHERE clause */
WHERE t_related.id IS NULL
_

これと同等です:

_SELECT
  t_main.*
FROM t_main 
WHERE 
  NOT EXISTS (
    SELECT t_related.id 
    FROM t_related 
    WHERE t_main.id = t_related.id
  )
_

しかし、これは等しくない等価です:

_t_main_に関連する行がある場合とない場合の両方で、_t_related_から行を返します。

_SELECT 
  t_main.*
FROM
  t_main
  LEFT OUTER JOIN t_related ON t_main.id = t_related.id
/* WHERE clause does not exclude NULL foreign keys */
_

これは、クエリのコンパイル方法と実行方法については触れていません。これも異なります。これは、クエリが返す行セットの比較に対処するだけです。

37

マイケルはすでにあなたの質問に答えたので、違いを説明するための簡単なサンプルです:

Table A
Key     Data
1       somedata1
2       somedata2

Table B
Key     Data
1       data1

左外部結合:

SELECT *
FROM A
LEFT OUTER JOIN B
ON A.Key = B.Key

結果:

Key     Data        Key     Data
1       somedata1   1
2       somedata2   null    null

EXISTSの使用:

SELECT *
FROM A WHERE EXISTS ( SELECT B.Key FROM B WHERE A.Key = B.Key )

存在しない:

SELECT *
FROM A WHERE NOT EXISTS ( SELECT B.Key FROM B WHERE A.Key = B.Key )

結果:

Key     Data        
2       somedata2
5
ntziolis

左外部結合は、存在しない場所よりも柔軟性があります。子テーブルから列を返す場合は、左外部結合を使用する必要があります。左外部結合を使用して、親テーブルに一致するレコードと、一致しない親テーブル内のすべてのレコードを返すこともできます。存在しない場所では、一致しないレコードのみを返すことができます。

ただし、それらが同等の行を返し、正しいテーブルに列が必要ない場合は、存在する場所がよりパフォーマンスの高い選択肢である可能性があります(少なくともSQLサーバーでは、他の場所については知りませんdbs)。

2
HLGEM

私は、OPが(機能的にが同じである場合にどの構成がより良いかを知りたいと思っていたと思います(つまり、セカンダリテーブルに一致がない行のみを表示したい)。

そのため、WHERE NOT EXISTSは常に同じくらい速くなるので、慣れるのが良い習慣です。

0
Hasski

結局のところ、答えはSQLでリレーショナル演算antijoinを実行するために両方が(他の構成体の中で)使用されていると思います。

0
onedaywhen