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)
パフォーマンスに違いはありますか?またはアルゴリズムの違い?
それとも単に構文上の砂糖ですか?
パフォーマンスに違いはありません。
ただし、最初のスタイルは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では構文エラーが発生します。
編集:もう少し明確化
syntaxだけではありません:意味的に正しいクエリを持つことです
編集、2011年12月
SQL Serverlogicalquery processing order はFROM、ON、JOIN、WHERE ...です.
したがって、「暗黙のWHERE内部結合」と「明示的なFROM外部結合」を混在させると、クエリが曖昧になるため、期待どおりの結果が得られない可能性があります...
違いは、読みやすさと保守性です。 SELECT * FROM a JOIN b ON a.ID = b.ID
正確な意図をすべて同じ場所に伝えます。
私は最後のクエリオプティマイザーの対象になっていないので、断定的には言いませんが、パフォーマンスに些細な違いがあれば、それを確認していると確信しています。
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を知らないことを示しています。それは私の個人的な意見です。
これを見て
これはこれの複製ですSO質問: 明示的vs暗黙的SQL結合 。一般的に、暗黙的(バージョン)は悪い形式であり、明示的ほど明確ではないと思います(バージョンについて)また、インプリシットは減価償却されていると思いますが、100%ではありません。実行計画はどちらでも同じです。
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 ...
_
これは、次のようなさまざまな理由で大きく異なります。
UNION
または他の集合演算を使用するときに邪魔になる場合があります。これはおそらくアスタリスク付きではありません。a.id
_または_b.id
_列はなくなり、id
列のみが存在します。 PostgreSQLはid
への参照の修飾を許可していますが(たとえば、あいまいさを解消する必要がある場合)、Oracleは許可していません。USING(...)
構文を使用した3番目のクエリでは、_a.*
_または_b.*
_の投影はOracleでは不可能になりました。