JOINキーワードを使用するかどうか


45

次のSQLクエリは同じです。

SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;

SELECT column1, column2
FROM table1 JOIN table2 
ON table1.id = table2.id;

そして確かに、私が試したすべてのDBMSで同じクエリプランが得られます。

しかし、時々、一方が他方よりも間違いなく優れているという意見を読んだり聞いたりします。当然、これらの主張は説明によって実証されることはありません。

私が働いている場所では、2番目のバージョンは他の開発者の大多数に好まれているようです。そのため、驚きを最小限に抑えるために、このスタイルに向かう傾向もあります。しかし、私の心の中で、私は本当に最初のものを考えています(それが最初にそれを学んだ方法だからです)。

これらの形式の1つは、他の形式よりも客観的に優れていますか?そうでない場合、一方を他方よりも使用する理由は何でしょうか?


1
それをプロファイリングして、結果を他の人に知らせてみませんか?一般的に、パフォーマンスはスタイル設定よりもはるかに重要です。
デミアンブレヒト

3
「これまで試したすべてのDBMSで同じクエリプランが得られます」これがパフォーマンスの面で答えを持っている場合、stackoverflow.comでそれを尋ねたでしょう。悲しいかな、彼らは同じクエリです。
SingleNegationElimination

Ah ..それを逃した:)
デミアンブレヒト

2
「主観的」とは「あなたの意見は」という意味ではありません。FAQに記載されている基準満たすために、これを編集しました。
アーロンノート

また、驚き最小限に抑えるために、このスタイルに向かう傾向があります。驚きは悪いです。
ピーターB

回答:


60

2番目の形式の方が優れていることがわかりました。それは私がそれを学んだ方法だからかもしれませんが、私は認めますが、私には1つの具体的な理由があります-懸念の分離。where句にテーブルを結合するために使用しているフィールドを置くと、クエリを理解するのが難しくなる可能性があります。

たとえば、次のクエリを実行します。

select *
from table1, table2, table3, table4
where table1.id = table2.id
and table2.id = table3.id
and table3.id = table4.id
and table1.column1 = 'Value 1'

上記のクエリには、テーブル結合条件と実際のビジネスロジック条件がすべて1つのスペースに結合されています。大きなクエリでは、これを理解するのは非常に困難です。

ただし、次のコードを使用してください。

select *
from table1 join table2 on table1.id = table2.id
join table3 on table2.id = table3.id
join table4 on table3.id = table4.id
where table1.column1 = 'Value 1'

この場合、テーブルまたはその関連方法に関係するものはすべてfrom句に分離されますが、クエリ制限の実際のビジネスロジックはwhere句にあります。これは、特に大規模なクエリの場合、はるかに理解しやすいと思います。


これは、特に2つのテーブルを通過した場合、または左、右、および完全結合の組み合わせが必要な場合に、唯一の賢明な方法です。
aglassman

5
。句はあなたが興味のあるデータのサブセットを指示する場所「懸念の分離」のために1は、一緒に持って来るデータを結合

39

結合構文は、1992年に古いコンマ構文を置き換えました。現在、コンマ構文でコードを記述する理由はありません。あなたは何も得ず、あなたはあなたがあなたが単に明示的な構文で持っていないいくつかの問題の対象となります。

そもそも、より複雑なクエリを取得すると、where条件が欠落することで偶発的なクロス結合が非常に簡単になります。これは、明示的な結合構文により、構文エラーが発生するのを防ぐことができるものです。

クロス結合を意図している場合、明示的な結合構文はそのことを明確にしますが、暗黙的な構文ではメンテナンスを行う人がwhere句を追加するのを忘れたと仮定する場合があります。

次に、暗黙的な構文を使用する少なくとも一部のデータベースで問題となる左結合と右結合の問題があります。これらはSQL Serverでは非推奨であり、実際には、古いバージョンでも正しい結果を実際に返すことはありません。外部結合を必要とするクエリには、SQL Serverの暗黙的な構文を含めないでください。

さらに、ここや他のサイトで、暗黙的結合と明示的結合を組み合わせたときに間違った結果が発生する(たとえば、左結合を追加するときに)質問があるので、それらを混合することはお勧めできません。

最後に、暗黙的な結合を使用する多くの人々は、実際には結合を理解していません。これは、データベースを効率的に照会するために必要な重要な理解です。


ご説明ありがとうございます。私が教えられたとき、私たちは両方の構文を見せられましたが、違いは説明されませんでした。私は時々、どこに行方不明のクエリを作成することができましたか。
-awiebe

8

ハ。PostgreSQLのドキュメントを見ながら、たまたま自分の質問に対する可能な答えを見つけました。このページの説明を要約すると、結果のクエリは同じですが、オプティマイザーが考慮する必要のあるプランの数は、結合の数とともに指数関数的に増加します。

このような結合が約6回行われた後、その数が非常に多くなり、クエリの計画に時間がかかる場合があります。また、約10回後、オプティマイザーは計画の徹底的な検索から確率的検索に切り替わり、最適な計画に到達しない場合があります。

実行時パラメーターを設定することにより、明示的に言及された内部結合とクロス結合を暗黙の結合とは異なる方法で処理し、それらを計画の先頭に強制し、他のオプションを探索しないようにプランナーに指示できます。

注目すべきは、デフォルトの動作はどちらの場合でも同じであり、代替プランを取得するには、異なる結果を得るためにdbmsの内部と問題のテーブルの特性に関する知識が必要です


2
ただし、これらのドキュメントを少し誤解しています。まず、実際には3つのしきい値があります。指摘したとおり、GEQOを起動します。他の2つ(fromおよびjoin collapse limit)は、プレーナーが結合順序を再編成するのではなく、適用可能なインデックスを選択することになります。第二に、同様に重要なこととして、クエリは解析されるときに書き換えられます。これにより、最初のサンプルクエリが2番目のクエリとまったく同じクエリツリーに解析されます。しきい値は、PGに結合の順序を変更するかどうかを通知します。
デニスドバーナルディ

8

さて、ここにそれの集合論的見解があります:

コンマを使用して2つ(またはそれ以上)のテーブル名を区切ると、意図するのはデカルト積になります。「左」テーブルのすべての行は、右テーブルの行と「一致」(連結)します。

ここで、where句に何かを記述すると、この「連結」に条件を設定して、どの行を「連結」するかを指示するようなものになります。

これは実際には行を「結合」します:)。したがって、より読みやすい構文を提供し、いくつかの一般的な値で「実際に」結合したいという理解しやすい結合キーワードです。@Dustinが上記で明らかにしたものに似ています。

現在、すべてのDBMSはスマートです。つまり、最初にデカルト積を計算してからデータをフィルタリングする(非常に無駄な)のではなく、クエリ構造に基づいて計算します。私が考えることができる唯一のことは、「参加」するように要求すると、参加アクティビティを明示的にするようなもので、おそらくコードをより速く実行するのに役立ちます(いくらですか?プロファイルして確認する必要があります)コンマ区切りの場合、最適な戦略を「図式化」するには時間がかかります。私は間違っているかもしれませんが、どのようにそれをコーディングするのかについて経験に基づいた推測をしています...


5

その場合は、一般にJOINステートメントを使用する方が良いと思います。

将来、ステートメントをINNER JOINからOUTER JOINに変更する必要がある状況が発生した場合、これは2番目のステートメントで行う方がはるかに簡単になります。


3

どのRDBMSでも、実行に関しては同じものになります。それは、人がより読みやすく表現力があるかどうかにかかっています。

JOINを使用して、次のように、結合の一致と実際の選択を明確にします。

select name, deptname
from people p, departments d
where p.deptid = d.id and p.is_temp = 'Y'

select name, deptname
from people p
    inner join departments d on p.deptid = d.id
where p.is_temp = 'Y'

後者の場合、どちらが結合条件であり、どちらが選択基準であるかがすぐにわかります。


1

異なる最適化のセットで2つの結果を見たことがありますが、メモリが提供される場合は、本当に毛深いクエリでms-sql2kにありました。その1つの例では、* =で使用された古い形式により、パフォーマンスが約4倍速くなりました。マイクロソフトの技術者を含む誰もその理由を説明できませんでした。MSの連中はそれを間違いだとラベル付けした。二度と見たことがない。

ほとんどのRDBMSは完全なデカルト座標を処理できないほど賢いので、(減価償却されていることを除けば)使用しないと考えることができる最大の理由は、私が働いた30-35歳未満のほとんどの人が以前の古い形式であり、遭遇するとひどく失われます。


もちろん、その左結合構文は、正しい結果を確実に提供することはありませんでした(SQL Server 2000のBOLを参照)。
HLGEM 14

私はそれに遭遇したことはなく、アスタリスクでの検索がうまく終了することはありません、あなたは例がありますか?
ビル14

-1

古いスタイルは廃止されているため、使用しないでください。

どちらが優れているかどうかという議論すらあるべきではありません。新しいコードでは古い構文を使用しないでください。


この答えは、非推奨で使用すべきではない理由を述べずに実際に何も追加しないと思います。
-RemcoGerlich

1
@RemcoGerlichが非推奨になった理由は、ここでは議論されていません。ここで議論されているのは、古い構文を使用するか新しい構文を使用するかです。一方が他方より優れているかどうかは重要ではありません。古い構文を使用するべきではありません。なぜ質問は別の議論です。(20年前に解決されたもの。)
ピーターB

-4

より簡潔な構文の理由の1つは、より簡潔であることです。したがって、使い慣れている場合は読みやすくなります。冗長なケースは、COBOLで算術を書き出すのに似ていると思います。たとえば、MULTIPLY A BY B GIVINGC。


Downvoters:この応答に事実上誤りがあるものはありますか、それとも単に「あなたに同意しない」ダウン投票ですか?
アダムリブシャ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.