27

SQL1:

select t1.f1,t2.f2 
from t1 
   left join t2 on t1.f1 = t2.f2 and t1.f2=1 and t1.f3=0 

SQL2:

select t1.f1,t2.f2 
from t1 
  left join t2 on t1.f1 = t2.f2 
where t1.f2=1 and t1.f3=0

違いはwhereandon句ですが、同じ結果を返しますか?違いは何ですか?DBMSはそれらを同じように実行しますか?ありがとう。

4

6 に答える 6

26

このwhere条項は結果セット全体に適用されます。onclauseは、問題の結合にのみ適用されます。

提供されている例では、結合の内側のフィールドに関連するすべての追加条件-したがって、この例では、2つのクエリは事実上同一です。

ただし、結合の外側のテーブルの値に条件を含めた場合は、大きな違いが生じます。

このリンクから詳細を入手できます:http://ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

例えば:

select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 and t2.f4=1

select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 where t2.f4=1

-さまざまなことを行います-前者はf4が1であるt2レコードへの結合を残しますが、後者は事実上t2への内部結合に戻されます。

于 2011-11-29T13:02:49.377 に答える
8

結合条件が2番目のクエリよりも具体的であるため、最初のクエリは2番目のクエリよりも高速です。where句でフィルタリングするレコードを返すことは意味がありません(まったく返さない方がよいでしょう-query1 )。

とにかく、それは本当にクエリオプティマイザに依存します。

以下をご覧ください。

JOINはWHEREよりも高速ですか?

于 2011-11-29T13:02:37.043 に答える
5

SQL構文について考えるときは、SQL操作の論理的な順序を理解することが重要です。句JOINの演算子です(そしてON関連するに属しますJOIN) 。FROMこの句は、論理的FROMに実行される最初の操作です(オプティマイザーは引き続き物​​事を並べ替えることを選択できます)。

あなたの例では、実際には違いはありませんが、との違いについてこのブログ投稿で示したように、簡単に構築できますブログONWHEREOUTER JOIN投稿の例ではSakilaデータベースを使用しています)。

最初のクエリ

SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
WHERE fa.film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;

収量:

ACTOR_ID  FIRST_NAME  LAST_NAME  COUNT
--------------------------------------
194       MERYL       ALLEN      1
198       MARY        KEITEL     1
30        SANDRA      PECK       1
85        MINNIE      ZELLWEGER  1
123       JULIANNE    DENCH      1

WHERE句で外部結合テーブルをフィルタリングしたため、LEFT JOINは事実上。に変換されましたINNER JOIN。なんで?映画に出演していない俳優がいた場合、その俳優の唯一の行にはが含まfa.film_id IS NULLれ、fa.film_id < 10述語はになりNULLます。このようなアクターは、と同様に結果から除外されINNER JOINます。

2番目のクエリ

SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
  AND fa.film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;

収量:

ACTOR_ID  FIRST_NAME  LAST_NAME     COUNT
-----------------------------------------
3         ED          CHASE         0
4         JENNIFER    DAVIS         0
5         JOHNNY      LOLLOBRIGIDA  0
6         BETTE       NICHOLSON     0
...
1         PENELOPE    GUINESS       1
200       THORA       TEMPLE        1
2         NICK        WAHLBERG      1
198       MARY        KEITEL        1

これで、述語がの述語のfa.film_id < 10一部であるため、映画のない俳優が結果に含まれます。LEFT JOINON

結論

常に論理的に最も意味のある場所に述語を配置します。

  • それらはあなたのJOIN操作の一部ですか?それらをに配置しますON
  • それらはあなたのJOIN製品全体にフィルターをかけていますか?それらをに配置しますWHERE
于 2020-03-05T16:34:44.483 に答える
3

2つのクエリは同一ではありません。

whereMark Ba​​nnisterは、この句は結果セット全体に適用されますが、onclauseは結合に適用されることを指摘しました。

あなたの場合、SQL 1 LEFT JOIN条件の場合、フィルターは右側で結合しますが、WHEREフィルタリングの前に常に左側が返されます。WHERE条件がないため、t1のすべてが常に返されます。

SQL 2では、LEFT JOIN条件により、右側に表示される一部の結果がフィルタリングされますが、ここでもすべてのt1が返されます。ただし、今回は、WHERE条件によってt1の一部のレコードが除外される可能性があります。

INSERT INTO `t1` (`f1`,`f2`,`f3`) VALUES (1,1,1); INSERT INTO `t2` (`f3`) VALUES (1);

それらは異なるロジックを指しているので、クエリはそれに基づいて作成する必要があり、それは私たちに大きな力と柔軟性を与えます。

ただし、INNER JOINは同じ結果を返すため、オプティマイザーを確認してください。

于 2018-04-19T07:01:38.383 に答える
2

関係代数により、WHERE句とINNER JOINの述語の互換性が可能になるため、WHERE句を使用したINNER JOINクエリでも、オプティマイザによって述語が再配置され、JOINプロセス中にすでに除外される可能性があります。

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

これには、INNER JOINを比較的「不完全」にしたり、フィルタリング基準のリストをより簡単に保守できるようにするために、いくつかの基準をWHEREに配置したりすることが含まれる場合があります。

このリンクから詳細を入手できます:http: //ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

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

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

もちろん、それは状況によって異なります。

于 2011-11-29T13:29:08.317 に答える
1

1)

SQL1: select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 **and** t1.f2=1 and t1.f3=0 

この場合、パーサーは、これら3つの条件でt1の各行とt2の各行をチェックします。より速い結果を得る。

2)SQL2: select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 **where** t1.f2=1 and t1.f3=0

この場合、joinは最初の条件のみを取り、joinから得られた結果はこれらの2つの条件でフィルタリングされます。また、最初のクエリよりも時間がかかります。

このリンクから詳細を入手できます:http://ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

于 2011-11-29T13:03:38.190 に答える