web-dev-qa-db-ja.com

SQL JOIN:USING、ON、またはWHEREの間に違いはありますか?

SQLがこれらの結合ステートメントで実行する方法に違いがあるかどうか疑問に思っていました。

SELECT * FROM a,b WHERE a.ID = b.ID

SELECT * FROM a JOIN b ON a.ID = b.ID

SELECT * FROM a JOIN b USING(ID)

パフォーマンスに違いはありますか?またはアルゴリズムの違い?

それとも単に構文上の砂糖ですか?

43
Yochai Timmer

パフォーマンスに違いはありません。

ただし、最初のスタイルはANSI-89で、一部のショップでは足を骨折します。私を含む。 2番目のスタイルはANSI-92で、より明確です。

例:

JOINとは、フィルターですか?

FROM T1,T2,T3....
WHERE T1.ID = T2.ID AND
     T1.foo = 'bar' AND T2.fish = 42 AND
     T1.ID = T3.ID

FROM T1 
   INNER JOIN T2 ON T1.ID = T2.ID
   INNER JOIN T3 ON T1.ID = T3.ID
WHERE
   T1.foo = 'bar' AND T2.fish = 42

OUTER JOIN(=**=)その後、2番目のスタイルは宣伝どおりに機能します。最初のものはSQL Server 2005以降ではサポートされない可能性があり、非推奨にもなっています

ANSI-92スタイルは、ボリックスも困難です。古いスタイルでは、条件を見逃した場合、簡単にデカルト積(クロス結合)になる可能性があります。 ANSI-92では構文エラーが発生します。

編集:もう少し明確化

  • "join the where"(暗黙的)を使用しない理由は、外部結合の結果が危険なためです。
  • 明示的なOUTER JOIN +暗黙のINNER JOINを使用する場合でも、問題のある結果が得られます+使用方法に一貫性がありません

syntaxだけではありません:意味的に正しいクエリを持つことです

編集、2011年12月

SQL Serverlogicalquery processing order はFROM、ON、JOIN、WHERE ...です.

したがって、「暗黙のWHERE内部結合」と「明示的なFROM外部結合」を混在させると、クエリが曖昧になるため、期待どおりの結果が得られない可能性があります...

53
gbn

違いは、読みやすさと保守性です。 SELECT * FROM a JOIN b ON a.ID = b.ID正確な意図をすべて同じ場所に伝えます。

私は最後のクエリオプティマイザーの対象になっていないので、断定的には言いませんが、パフォーマンスに些細な違いがあれば、それを確認していると確信しています。

4
Pete M

WHEREを使用して結合を強制すると、私は軽蔑します。それは私には正しく見えません、汚いハックです。適切なANSI結合はONを使用することです:

SELECT 
    p.Product,
    o.Order
FROM 
    Product p
INNER JOIN
    Order o
ON
    o.OrderID = p.OrderID

結合時にはONを使用し、結果をフィルタリングするにはWHEREを使用することをお勧めします。 WHEREは、結果をフィルター処理する場所によってグループ化および順序付けする以外に、最後に使用するものの1つであることを覚えておいてください。したがって、読みにくいので、WHEREを使用してテーブルを結合しないでください。

SELECT 
    p.Product,
    o.Order
FROM 
    Product p
INNER JOIN
    Order o
ON
    o.OrderID = p.OrderID
WHERE
    o.Category = 'IT'

結局のところ、あなた(開発者)は将来存在しない可能性があるので、可読性と保守性は、コードを引き継ぐ必要のある魂を注ぐのに役立ちます:).

開発者がWHEREを使用してテーブルを結合しているのを見ると、それは通常、十分なT-SQLを知らないことを示しています。それは私の個人的な意見です。

2
JonH
0
Jason

これはこれの複製ですSO質問: 明示的vs暗黙的SQL結合 。一般的に、暗黙的(バージョン)は悪い形式であり、明示的ほど明確ではないと思います(バージョンについて)また、インプリシットは減価償却されていると思いますが、100%ではありません。実行計画はどちらでも同じです。

0
scrappedcola

USING(...)構文についての回答はまだありません。

これらの2つのクエリは論理的に同等ですが、最新のオプティマイザの観点からも次のようになります。

_SELECT * FROM a, b WHERE a.id = b.id
SELECT * FROM a JOIN b ON a.id = b.id
_

これは少し異なるセマンティクスを持っています:

_SELECT * FROM a JOIN b USING (id)
_

次のスキーマを想定しています。

_CREATE TABLE a (id int, a1 int, a2 int);
CREATE TABLE b (id int, b1 int, b2 int);
_

最初の2つのクエリでは、アスタリスクが次のように拡張されます。

_SELECT a.id, a.a1, a.a2, b.id, b.a1, b.a2 FROM ...
_

一方、3番目のクエリでは、アスタリスクが次のように展開されます。

_SELECT coalesce(a.id, b.id) AS id, a.a1, a.a2, b.a1, b.a2 FROM ...
_

これは、次のようなさまざまな理由で大きく異なります。

  • 投影された列の数は6ではなく5になりました。これは、UNIONまたは他の集合演算を使用するときに邪魔になる場合があります。これはおそらくアスタリスク付きではありません。
  • 修飾された(そして重複した)_a.id_または_b.id_列はなくなり、id列のみが存在します。 PostgreSQLはidへの参照の修飾を許可していますが(たとえば、あいまいさを解消する必要がある場合)、Oracleは許可していません。
  • 結果として、USING(...)構文を使用した3番目のクエリでは、_a.*_または_b.*_の投影はOracleでは不可能になりました。
0
Lukas Eder