SQLでは、IDに基づいて結果をフィルタリングしようとしていますが、間に論理的な違いがあるかどうか疑問に思っています
SELECT value
FROM table1
JOIN table2 ON table1.id = table2.id
WHERE table1.id = 1
そして
SELECT value
FROM table1
JOIN table2 ON table1.id = table2.id AND table1.id = 1
私には、常に同じ結果のセットが得られますが、ロジックが異なるように見えますが、2つの異なる結果セットが得られるような条件があるのか(または常にまったく同じ2つの結果セットが返されるのか) )
答えは[〜#〜] no [〜#〜]違いですが、次のとおりです。
私はいつも次のことをすることを好みます。
ON
句に常に保持するwhere
句に入れますこれにより、クエリが読みやすくなります。
したがって、このクエリを使用します。
SELECT value
FROM table1
INNER JOIN table2
ON table1.id = table2.id
WHERE table1.id = 1
ただし、OUTER JOIN'S
を使用している場合、ON
条件とWhere
条件でフィルターを維持することには大きな違いがあります。
論理クエリ処理
次のリストには、クエリの一般的な形式と、さまざまな句が論理的に処理される順序に従って割り当てられたステップ番号が含まれています。
(5) SELECT (5-2) DISTINCT (5-3) TOP(<top_specification>) (5-1) <select_list>
(1) FROM (1-J) <left_table> <join_type> JOIN <right_table> ON <on_predicate>
| (1-A) <left_table> <apply_type> APPLY <right_table_expression> AS <alias>
| (1-P) <left_table> PIVOT(<pivot_specification>) AS <alias>
| (1-U) <left_table> UNPIVOT(<unpivot_specification>) AS <alias>
(2) WHERE <where_predicate>
(3) GROUP BY <group_by_specification>
(4) HAVING <having_predicate>
(6) ORDER BY <order_by_list>;
フロー図の論理クエリ処理
(1)FROM:FROMフェーズでは、クエリのソーステーブルを識別し、テーブル演算子を処理します。各テーブル演算子は一連のサブフェーズを適用します。たとえば、結合に含まれるフェーズは、(1-J1)デカルト積、(1-J2)ONフィルター、(1-J3)外部列の追加です。 FROMフェーズでは、仮想テーブルVT1が生成されます。
(1-J1)デカルト積:このフェーズでは、テーブル演算子に含まれる2つのテーブル間でデカルト積(クロス結合)を実行し、VT1-J1を生成します。
この優れたリンクから参照されます。
VR46が指摘したように、INNER JOINSを使用しても違いはありませんが、OUTER JOINSを使用して2番目のテーブルの値を評価すると(左結合の場合)大きな違いがあります。 -右結合の最初のテーブル)。次の設定を検討してください。
DECLARE @Table1 TABLE ([ID] int)
DECLARE @Table2 TABLE ([Table1ID] int, [Value] varchar(50))
INSERT INTO @Table1
VALUES
(1),
(2),
(3)
INSERT INTO @Table2
VALUES
(1, 'test'),
(1, 'hello'),
(2, 'goodbye')
左外部結合を使用してそこから選択し、where句に条件を配置すると、次のようになります。
SELECT * FROM @Table1 T1
LEFT OUTER JOIN @Table2 T2
ON T1.ID = T2.Table1ID
WHERE T2.Table1ID = 1
次の結果が得られます。
ID Table1ID Value
----------- ----------- --------------------------------------------------
1 1 test
1 1 hello
これは、where句が結果セットを制限するため、IDが1のtable1のレコードのみが含まれるためです。ただし、条件をon句に移動すると、次のようになります。
SELECT * FROM @Table1 T1
LEFT OUTER JOIN @Table2 T2
ON T1.ID = T2.Table1ID
AND T2.Table1ID = 1
次の結果が得られます。
ID Table1ID Value
----------- ----------- --------------------------------------------------
1 1 test
1 1 hello
2 NULL NULL
3 NULL NULL
これは、table1のID 1によって結果セットをフィルターするのではなく、JOINをフィルターするためです。したがって、2番目のテーブルでtable1のID 2が一致しても、それは結合から除外されますが、結果セット(したがってnull値)からは除外されません。
したがって、内部結合の場合は重要ではありませんが、読みやすさと一貫性を保つためにwhere句に保持する必要があります。ただし、外部結合の場合、結果セットに影響を与えるため、条件をどこに置くかが問題になることに注意する必要があります。
「正しい」と答えたのは正しくないと思います。どうして?説明してみます:
意見があります
「常にON句に結合条件を保持する常にフィルタをwhere句に配置する」
そして、これは間違っています。内部結合を使用している場合は、フィルターパラメーターを毎回ON句に配置します。場所には配置しません。なぜですか?複雑なWHERE句(たとえば、関数や計算の使用)を使用した、合計10個のテーブル(つまり、すべてのテーブルに10kのレコードがある)結合の複雑なクエリを想像してみてください。 ON句にフィルタリング条件を指定すると、これらの10個のテーブル間のJOINSは発生せず、WHERE句はまったく実行されません。この場合、WHERE句で10000 ^ 10の計算を実行していません。これは理にかなっており、WHERE句のみにフィルタリングパラメータを配置することはできません。