1048

簡単にするために、関連するすべてのフィールドが であると仮定しますNOT NULL

できるよ:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1, table2
WHERE
    table1.foreignkey = table2.primarykey
    AND (some other conditions)

またはそうでなければ:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1 INNER JOIN table2
    ON table1.foreignkey = table2.primarykey
WHERE
    (some other conditions)

これら 2 つは で同じように機能しMySQLますか?

4

12 に答える 12

762

INNER JOIN使用すべき ANSI 構文です。

特に多くのテーブルを結合する場合は特に、読みやすいと一般的に考えられています。

OUTER JOINまた、必要に応じていつでも簡単に交換できます。

構文は、WHEREよりリレーショナル モデル指向です。

2 つのテーブルJOINed の結果は、結合列が一致する行のみを選択するフィルターが適用されたテーブルのデカルト積です。

WHERE構文でこれを確認する方が簡単です。

あなたの例では、MySQL (および一般的に SQL) では、これら 2 つのクエリは同義語です。

また、MySQL にもSTRAIGHT_JOIN句があることに注意してください。

この句を使用すると、JOIN順序を制御できます。つまり、どのテーブルが外側のループでスキャンされ、どのテーブルが内側のループでスキャンされます。

WHERE構文を使用して MySQL でこれを制御することはできません。

于 2009-06-19T16:17:28.200 に答える
211

INNER JOIN人間の可読性に役立つと指摘する人もいますが、それが最優先事項であることに同意します。結合構文が読みやすい理由
を説明してみましょう。

基本的なSELECTクエリは次のとおりです。

SELECT stuff
FROM tables
WHERE conditions

このSELECT句は、を返すかを示しています。このFROM句は、どこから取得しているかを示し、どのWHERE句を取得しているかを示します。

JOINは、テーブルがどのように結合されるか (概念的には、実際には 1 つのテーブルに) に関するステートメントです。

テーブルを制御するすべてのクエリ要素 (データを取得する場所) は、意味的には句に属しますFROM(もちろん、そこにJOIN要素が入ります)。join-elements をWHERE句に入れると、whichwhere-from が混同されます。そのため、JOIN構文が優先されます。

于 2009-06-19T16:30:59.527 に答える
153

ON / WHERE での条件ステートメントの適用

ここでは、論理クエリの処理手順について説明しました。


参照: Inside Microsoft® SQL Server™ 2005 T-SQL Querying
発行元: Microsoft Press
Pub 日付: 2006 年 3 月 7 日
印刷版 ISBN-10: 0-7356-2313-9
印刷版 ISBN-13: 978-0-7356-2313-2
ページ: 640

Microsoft® SQL Server™ 2005 T-SQL クエリの内部

(8)  SELECT (9) DISTINCT (11) TOP <top_specification> <select_list>
(1)  FROM <left_table>
(3)       <join_type> JOIN <right_table>
(2)       ON <join_condition>
(4)  WHERE <where_condition>
(5)  GROUP BY <group_by_list>
(6)  WITH {CUBE | ROLLUP}
(7)  HAVING <having_condition>
(10) ORDER BY <order_by_list>

他のプログラミング言語と異なる SQL の最初の顕著な側面は、コードが処理される順序です。ほとんどのプログラミング言語では、コードは記述された順序で処理されます。SQL では、処理される最初の句は FROM 句ですが、最初に現れる SELECT 句はほぼ最後に処理されます。

各ステップでは、次のステップへの入力として使用される仮想テーブルが生成されます。これらの仮想テーブルは、呼び出し元 (クライアント アプリケーションまたは外部クエリ) には使用できません。最後のステップで生成されたテーブルのみが呼び出し元に返されます。クエリで特定の句が指定されていない場合、対応するステップは単純にスキップされます。

論理問合せ処理フェーズの簡単な説明

今のところ、手順の説明があまり意味をなさないと思われる場合でも、あまり心配する必要はありません。これらは参照として提供されます。シナリオの例の後のセクションでは、手順についてさらに詳しく説明します。

  1. FROM: FROM 句の最初の 2 つのテーブル間でデカルト積 (クロス ジョイン) が実行され、その結果、仮想テーブル VT1 が生成されます。

  2. ON: VT1 に ON フィルターをかけます。が TRUEである行だけ<join_condition>が VT2 に挿入されます。

  3. OUTER (結合): OUTER JOIN が指定されている場合 (CROSS JOIN または INNER JOIN とは対照的に)、保存されたテーブルまたは一致が見つからなかったテーブルからの行は、外側の行として VT2 からの行に追加され、 VT3。FROM 句に 3 つ以上のテーブルがある場合、最後の結合の結果と FROM 句の次のテーブルの間で、すべてのテーブルが処理されるまで、手順 1 ~ 3 が繰り返し適用されます。

  4. WHERE: VT3 に WHERE フィルターが適用されます。が TRUEである行だけ<where_condition>が VT4 に挿入されます。

  5. GROUP BY: VT4 からの行は、GROUP BY 句で指定された列リストに基づいてグループに配置されます。VT5 が生成されます。

  6. キューブ | ROLLUP: VT5 からの行にスーパーグループ (グループのグループ) が追加され、VT6 が生成されます。

  7. HAVING: VT6 に HAVING フィルターが適用されます。が TRUEのグループだけが<having_condition>VT7 に挿入されます。

  8. SELECT: SELECT リストが処理され、VT8 が生成されます。

  9. DISTINCT: 重複行は VT8 から削除されます。VT9 が生成されます。

  10. ORDER BY: VT9 の行は、ORDER BY 句で指定された列リストに従って並べ替えられます。カーソルが生成されます (VC10)。

  11. TOP: VC10 の先頭から指定された数または割合の行が選択されます。テーブル VT11 が生成され、呼び出し元に返されます。



したがって、(INNER JOIN) ON は、WHERE 句を適用する前にデータをフィルター処理します (ここで VT のデータ数自体が減少します)。後続の結合条件は、パフォーマンスを向上させるフィルタリングされたデータで実行されます。その後、WHERE 条件のみがフィルター条件を適用します。

(ON / WHERE で条件ステートメントを適用しても、いくつかのケースでは大きな違いはありません。これは、結合したテーブルの数と、各結合テーブルで使用可能な行の数によって異なります)

于 2009-12-22T06:24:07.403 に答える
70

暗黙の結合 ANSI 構文は古く、あまり明白ではないため、推奨されません。

さらに、リレーショナル代数では、WHERE句との述語の交換が可能であるため、句を含むクエリでINNER JOINも、オプティマイザによって述語が再配置される可能性があります。INNER JOINWHERE

できるだけ読みやすい方法でクエリを作成することをお勧めします。

これには、フィルタリング基準のリストをより簡単に維持できるようにするために、INNER JOIN比較的「不完全」なものを作成したり、単純にいくつかの基準を に入れたりすることが含まれます。WHERE

たとえば、次の代わりに:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

書く:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

しかし、それはもちろん依存します。

于 2009-06-19T16:23:45.003 に答える
34

暗黙の結合 (最初のクエリとして知られているもの) は、クエリにテーブルを追加し始める必要があると、はるかに混乱し、読みにくく、維持しにくくなります。4 つまたは 5 つの異なるテーブルで同じクエリとタイプの結合を行うことを想像してみてください。悪夢です。

明示的な結合 (2 番目の例) を使用すると、はるかに読みやすく、保守が容易になります。

于 2009-06-19T16:19:14.940 に答える
28

また、古い構文を使用するとエラーが発生しやすくなることも指摘します。ON 句なしで内部結合を使用すると、構文エラーが発生します。古い構文を使用していて、where 句の結合条件の 1 つを忘れると、クロス結合が発生します。開発者は、distinct キーワードを追加することでこれを修正することがよくあります (結合自体が壊れていることにまだ気付いていないため、結合を修正するのではなく)。これにより、問題が解決したように見えますが、クエリが大幅に遅くなります。

さらにメンテナンスのために、古い構文でクロス結合を使用している場合、メンテナは、クロス結合を使用するつもりだったのか (クロス結合が必要な場合もあります)、または修正する必要がある事故だったのかをどのように知ることができますか?

この質問を指摘して、左結合を使用する場合に暗黙の構文がなぜ悪いのかを確認しましょう。 Sybase *= 同じ内部テーブルに対して 2 つの異なる外部テーブルを持つ Ansi 標準へ

さらに (ここでの個人的な怒り)、明示的な結合を使用する標準は 20 年以上前のものです。つまり、暗黙的な結合構文は 20 年間時代遅れになっています。20 年も前から使われている構文を使用してアプリケーション コードを記述しますか? なぜデータベースコードを書きたいのですか?

于 2009-06-19T16:46:59.837 に答える
13

人間が読める意味が異なります。

ただし、クエリ オプティマイザによっては、マシンにとって同じ意味を持つ場合があります。

コードは常に読みやすいものにする必要があります。

つまり、これが組み込みの関係である場合は、明示的な結合を使用します。関連性の弱いデータを照合する場合は、where 句を使用します。

于 2009-06-19T16:20:49.900 に答える
5

MySQL について話していることは知っていますが、とにかく: Oracle 9 では、明示的な結合と暗黙的な結合によって異なる実行計画が生成されます。Oracle 10以降で解決されたAFAIK:そのような違いはもうありません。

于 2009-06-19T17:03:42.483 に答える
2

ANSI 結合構文は、明らかに移植性が高くなります。

私は Microsoft SQL Server のアップグレードを行っています。また、SQL Server の外部結合の =* および *= 構文は、2005 SQL Server 以降では (互換モードなしで) サポートされていないことにも言及します。

于 2009-06-19T16:50:12.830 に答える