私はSQLクエリの実行の論理的な順序を知っています:
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
たとえば、次のようなクエリがある場合、クエリに複数の結合があるとどうなりますか。
SELECT *
FROM user_branch T1
INNER JOIN dimcustomer2 T2
ON T1.BRANCH_CODE = T2.BRANCH_CODE
INNER JOIN customer_guarantee T3
ON T3.CUSTOMER_NUM = T2.CUSTOMER_NUM
データの例:
customer_guarantee: CUSTOMER_NUM BRANCH_CODE
-------------------------------
A X
B X
C Y
D Z
user_branch: USER_ID BRANCH_CODE
--------------------------------
U1 Y
dimcustomer2: CUSTOMER_NUM BRANCH_CODE
--------------------------------
A Y
B Y
C Y
D Z
これはどのように実行されますか?どの結合が最初に実行されますか?そして、クエリに異なる種類の結合がある場合はどうなりますか?その場合、結合を実行する順序はどうなりますか?前もって感謝します。
結合の論理的な順序を決定する1つの方法は、例の最初の内部結合を左外部結合に置き換えることです。
SELECT *
FROM user_branch T1
LEFT JOIN dimcustomer2 T2
ON T1.BRANCH_CODE = T2.BRANCH_CODE
INNER JOIN customer_guarantee T3
ON T3.CUSTOMER_NUM = T2.CUSTOMER_NUM
T1
の一部の行がT2
に一致しないと仮定します。より具体的には、これらが3つのテーブルであると仮定します。
T1 T2 T3
BRANCH_CODE BRANCH_CODE CUSTOMER_NUM CUSTOMER_NUM
----------- ----------- ------------ ------------
11 11 230 120
12 12 235 170
13 15 260 230
14 235
15 245
250
260
270
ここには2つの結合があり、それらが実行される順序には2つの可能性があります。
左結合が最初に評価される場合、その結果はT2
行が一致しなかったT1
列にnullが含まれます。
T1.BRANCH_CODE T2.BARNCH_CODE T2.CUSTOMER_NUM -------------- -------------- --- ------------ 11 11 230 12 12 235 13 (ヌル)(ヌル) 14 (ヌル)(ヌル) 15 15 260
T3
列を使用する条件で内部結合を使用して、T2
でその結果をさらに結合すると、一致しない、つまり対応するT1
行が削除されます。これは、nullが結合の等号条件を満たすことができないためです。
T1.BRANCH_CODE T2.BARNCH_CODE T2.CUSTOMER_NUM T3.CUSTOMER_NUM -------------- -------------- --------------- --------------- 11 11 230 230 12 12 235 235 15 15 260 260
このようにして、T1
行の一部が最終的な結果セットから除外されます。
内部結合が最初に実行されると、内部結合の条件に一致するT2
およびT3
の行を含む結果セットが生成されます。
T2.BARNCH_CODE T2.CUSTOMER_NUM T3.CUSTOMER_NUM -------------- ---------------- ------------- 11 230 230 12 235 235 15 260 260
この結果セットがT1
に外部結合され、T1
が外部にある場合、T1
からのすべての行と、外部結合条件に一致するT2
-T3
内部結合からの行を含む最終結果が得られます。
T1.BRANCH_CODE T2.BARNCH_CODE T2.CUSTOMER_NUM T3.CUSTOMER_NUM -------------- -------------- --------------- --------------- 11 11 230 230 12 12 235 235 13 (ヌル)(ヌル)(ヌル) 14 (ヌル)(ヌル)(ヌル) 15 15 260 260
したがって、この2番目の解釈は、すべてのT1
行が結果に存在する必要があることを意味します。
これらの2つの解釈はそのような異なる結果を与えるので、1つだけが真であることは明らかです。クエリを実行すると、実際には最初のクエリであることがわかります。つまり、論理的には、結合はFROM
句で指定された順序で実行されます。
上記の結論は、最も一般的な結合構文、つまりこれに適用されることに注意してください。
FROM
T1
... JOIN T2 ON ...
... JOIN T3 ON ...
...
あなたの例はそのパターンに一致するので、結論もそれに当てはまります。しかし、私たちの結論が当てはまらない、または少なくともそれほど単純ではない場合に言及する価値のあるバリエーションがあります。
構文的には、次のように、結合を別の結合内に指定できます。
FROM
T1
JOIN
T2
JOIN T3 ON ..
ON ...
上記の場合、JOIN T2
の前にJOIN T3
が出現します。ただし、前の結合の宣言はその時点では完了していません。そのON
副次句は最後のものであり、JOIN T3 ON ...
部分の後でのみ論理的に評価されます。したがって、この場合、T2
は最初にT3
に結合され、次に結合の結果がT1
に結合されます。
あなたは、私たちの結論がここにあると主張しますが、この状況ではそれほど明確ではありません。結合は、FROM
句でspecifiedの順序で評価されると結論付けました。この例では、FROM
句を解析するときに最初に遭遇する結合は、2番目の結合の時点ではまだ完全に指定されていません。
明示的なJOIN
構文が導入される前は、結合は次のように指定されていました。
FROM
T1,
T2,
T3
WHERE
<joining conditions, filter conditions>
このタイプの結合は、コンマ結合と呼ばれることもありますが、SQL Serverを含む、すべてではないにしても、ほとんどのプラットフォームでサポートされています。
結合条件がない場合、コンマ結合は基本的にクロス結合です。結合条件は、それを内部結合にします。ただし、この場合の結合条件は、まったく別の句、WHERE
句に入っていることがわかります。
SQL Serverでは、同じFROM
句にコンマ結合と従来の結合を混在させることができます。次のような結合が混在している場合:
FROM
T1,
T2
JOIN T3 ON ... ,
T4 ...
SQL Serverは、コンマで区切られた個々の項目を互いに独立して評価してから、それらをすべて結合します。したがって、上記の場合、T2 JOIN T3 ON ...
結合は、その結果がT1
にクロス結合される前に評価されます(WHERE
句で検出される可能性のある結合条件によってさらにフィルタリングされます)。ここでの結論はまったく当てはまりません。ただし、この場合、非常に異なる構文が使用されていることがわかります。
スタックオーバーフローに関する私の回答で混合構文について少し詳しく説明します: マルチパート識別子をバインドできませんでした 。
「論理的実行」というフレーズはあまり意味がありません。クエリ実行は、定義により、結果セットの物理的な具体化です。 「論理的実行」とは、クエリのコンパイル、つまりクエリ構文と意味の意味が分析され、クエリの計画がその意味の意味を実装するために準備されるフェーズであると私は思います。
結合されたテーブル1 クエリでは常に左から右(または上から下)に評価されます。
select ... from t_a -- evaluated first
join t_b -- evaluated second
on t_a.c1 = t_b.c3
join t_x -- evaluated third
on t_b.c4 = t_x.c5
...
評価シーケンスの後半に含まれるテーブルに属する列をON
句で参照しようとすると、これを自分で確認できます。これはコンパイルに失敗します:
select ... from t_a
join t_b
on t_a.c1 = t_c.c8 -- t_c is not known yet
join t_c
...
クエリが解析された後、実行プランは、クエリのセマンティクスを維持するanyの順序で結合を実行できます。 マニュアルによると 、
FROM
キーワードの後のテーブルソースの順序は、返される結果セットには影響しません。
このQ&A はある程度関連しています。
1-joined_table
句は、2つのtable_source
sとそれに対応するON
句で構成されます。
すべてのJOINは実際にはFROM句に属しています。意味的には、ON句を維持し、LEFT/RIGHT OUTER JOIN句を使用しない限り、JOINが書き込まれる順序に違いはありません。言い換えると、FROM句とJOIN句の出力は単一の大きなリレーションであり、列がどの順序であるかは実際には問題ではありません。これはデータベースオプティマイザーにとって重要な最適化の機会であるため、これは非常に重要です。WHERE条件によってプルーニングされる可能性がある場合は、最初に小さいリレーション間でJOINを実行するのが理にかなっています。この方法では、結果セットの残りの部分を処理するときに、データベースがこれらの列をキャッシュする方が現実的です。