したがって、SQLでいくつかのことがどのように機能するかは知っていますが、その理由はわかりません。また、オンラインでこれに関する素人の素敵な説明を見つけることができません。参考までに、私は Oracle 11g と TOAD を使用しています。
質問 1 - 条件付きの外部結合
外部結合テーブルに条件を配置すると、構文に関係なくクエリが内部結合に変わることを私は知っています。したがって、このクエリは内部結合として機能します。
SELECT a.field1, b.field1
FROM tableA a
LEFT JOIN tableB b on a.key = b.key
WHERE b.field2 = 'someCriteria'
これを回避するには、2 番目のテーブルの条件に「OR IS NULL」を含めます。私はこれが真実であることを知っていますが、これがなぜなのかを理解することはできませんでした. 外部テーブルの基準が外部結合を内部結合に変える理由を誰かが説明できますか?
質問 2 - さまざまな条項に基準を追加すると結果が変わる
上記が真実であるため、基準の順序が次の2つのクエリの結果をどのように変更できるかについて苦労してきました。tableA と tableB の 2 つのテーブルがあり、tableA のサブセットと tableB のサブセットの左結合比較を行う必要があります。
SQL1
SELECT DISTINCT a.field1, b.field2
FROM tableA a
LEFT JOIN tableB b
on a.key = b.key
AND (b.field2 = 'somecriteria' or b.field2 IS NULL)
WHERE a.field1 = 'othercriteria'
結果: SQL1 は正しい左結合の結果を示します。
SQL2
SELECT DISTINCT a.field1, b.field2
FROM tableA a
LEFT JOIN tableB b
on a.key = b.key
WHERE a.field1 = 'othercriteria'
AND (b.field2 = 'somecriteria' or b.field2 IS NULL)
結果: SQL2 は、2 つのサブセットの内部結合結果のみを引き出します (tableB に一致しない tableA の行を除く)。
結果を理解する
この理由は、join と where が実行される順序と関係があります。この変化するパフォーマンスは理解できましたが、構文がほぼ同じであるため、結果が変化する理由についてはわかりません。頭を包み込むために、両方のクエリの実行計画を実行し、次の結果を得ました (TOAD から)。
実行計画:
SQL 1:
- 5) Select ステートメント (Select ステートメントによって行が返されました)
- 4) 一意に並べ替え (手順 3 の行は、重複行を排除するために並べ替えられました)
- 3) Hash Join Right Outer (手順 1、2 の結果セットを結合 (ハッシュ)
- 1) Table Access Full TABLE tableB (テーブル tableB のすべての行が読み取られる)
- 2) Table Access Full TABLE tableA (テーブル tableA のすべての行が読み取られる)
- 3) Hash Join Right Outer (手順 1、2 の結果セットを結合 (ハッシュ)
SQL 2:
- 11) Select ステートメント (Select ステートメントによって行が返されました)
- 10) 一意に並べ替え (手順 9 の行は、重複行を排除するために並べ替えられました)
- 9) 手順 4、8 からのすべての個別の行が返されました
- 4) フィルター (ステップ 3 で返された行について、フィルター条件に応じて行を除外します)
- 3) Hash Join Right Outer (手順 1、2 の結果セットを結合 (ハッシュ)
- 1) Table Access Full TABLE tableB (テーブル tableB のすべての行が読み取られる)
- 2) Table Access Full TABLE tableA (テーブル tableA のすべての行が読み取られる)
- 8) フィルター (ステップ 7 で返された行について、フィルター基準に応じて行をフィルターで除外します)
- 7) Hash Join Right Outer (手順 5、6 の結果セットを結合 (ハッシュ)
- 5) Table Access Full TABLE tableB (テーブル tableB のすべての行が読み取られる)
- 6) Table Access Full TABLE tableA (テーブル tableA のすべての行が読み取られる)
- 4) フィルター (ステップ 3 で返された行について、フィルター条件に応じて行を除外します)
したがって、上記の実行計画は、SQL 2 が SQL 1 とは異なる結果をもたらす理由を完全に説明していることに疑いの余地はありませんが、これらの計画を読むのに苦労しています。誰かがこれらの実行計画を翻訳するのを手伝ってくれますか? tableA 条件が JOIN の代わりに WHERE 句にリストされているため、SQL2 が内部結合として扱われる理由を説明できますか?
前もって感謝します!!