web-dev-qa-db-ja.com

MySQLのLEFT JOINがWHERE句を使用しているときに「NULL」レコードを返すのはなぜですか?

今日、より複雑なMySQLクエリをいくつか試しましたが、MySQLのLEFT JOINがWHERE句で機能していないことに気付きました。つまり、一部のレコードは返されますが、右側が空のレコードは返されません。

たとえば、テーブルがあるとします。

アルバム; albums_rap 
 idアーティストタイトルトラック; idアーティストタイトルランク
 ---- -------- ---------- ---------------; ---- --------- ----- -------------- 
 1 John Doe Mix CD 20; 3マークCD#7 15 
 2マークCD#7 35;

そして、私がこのクエリを実行すると:

SELECT 
    t1.artist as artist,
    t1.title as title,
    t1.tracks as tracks,
    t2.rank as rank,
FROM
    albums as t1
LEFT JOIN
    albums_rap as t2
ON 
    t1.artist LIKE t2.artist
AND
    t1.title LIKE t2.title
WHERE
    t2.rank != 17

私はこれを手に入れます:

アーティストタイトルトラックランク
 ------ ----- ------ ----- 
 Mark CD#7 35 15

しかし、このクエリで「WHERE」を「AND」に置き換えると、次のようになります。

アーティストタイトルトラックランク
 ------ --------- ------ ----- 
 Mark CD#7 35 15 
 John Doe Mix CD 20 NULL

最初のレコードが「NULL」のレコードを返さない理由(nullは17と等しくない...)

あなたが私が何を言っているのか理解していただけたら幸いです。どういうわけか私に違いを説明してください。英語が下手で申し訳ありませんが、母国語ではありません。

10
nass

左結合条件とwhere条件フィルターはどちらも同じではありません。物理的な結合が行われた後、データはwhere句によってフィルタリングされます。左側の結合を見ると、通常は左側のテーブルからすべての行が返されますが、where句を指定すると、結合の出力がフィルタリングされるため、結果は内部結合のようになります。下の画像の左側にある2つの図に注目してください。

enter image description here

30
akhila vangala

最初のケース:

結合後、レコードは(WHERE句)によってフィルタリングされます。したがって、結果は1つだけです。

2番目のケース(WHEREをANDに置き換えた場合)

すべての結合エントリと2番目の条件(t2.rank!= 17)で満たされたエントリを返します。そのため、ここでは2つのレコードを取得しています(1つは結合から、もう1つはAND句から)

2

この質問に対する解決策は、SQLステートメントの実行順序または論理クエリ処理フェーズを理解すると、非常に直感的になります。順序は:-

1. FROM
2. ON
3. OUTER
4. WHERE
5. GROUP BY
6. CUBE | ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP

JOINのOUTER(LEFT/RIGHT)部分(NULL値の行を追加)の前にONが実行されるため、1番目のケースでは、ランク列にNULL値の行があります。 2番目のケースでは、OUTER JOIN(ここではLEFT JOIN)が実行された後、行がランク列の値に基づいてフィルターで除外されます。したがって、ランク列にNULL値を含む行は除外されます。

SQLクエリで気づくことができる1つの非常に重要なことは、NULLとの比較ですこの領域は、NULL/NON-の場合、NULL値として特別な注意が必要です通常の算術演算子を使用したNULL値は、比較に使用できる値がないことを意味するため、NULL(TRUEでもFALSEでもない)になります。この動作はANSI SQL-92標準で定義されています。(これは、一部のSQLでansi null(実際の名前は異なる場合があります)パラメータをオフにすることでオーバーライドできます。プロセッサ)したがって、where句を使用したSQLクエリは、「17!= NULL」が原因で直感に反する可能性があるため、ランク列にNULL値を含む行を除外します。

NULL = NULLはNULL/UNKNOWNを返します

17 = NULLはNULL/UNKNOWNを返します

17!= NULLの結果NULL?UNKNOWN

参考になる興味深い投稿/ブログは次のとおりです。

http://blog.sqlauthority.com/2009/04/06/sql-server-logical-query-processing-phases-order-of-statement-execution/http:/ /blog.sqlauthority.com/2009/03/15/sql-server-interesting-observation-of-on-clause-on-left-join-how-on-clause-effects-resultset-in-left-join/http://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/

2
Aditya Guru

「LEFT JOINキーワードは、左側のテーブル(table1)からすべての行を返し、右側のテーブル(table2)の一致する行を使用します。一致がない場合、結果は右側でNULLになります。 。」

上記の引用は w3schools.com からのものです

ただし、WHERE句をLEFT JOINに配置すると、SQLはそれをINNER JOINとして扱い、次のようになります。

「両方のテーブルの列が一致する限り、INNER JOINキーワードは両方のテーブルからすべての行を選択します。」

w3schools.com からも引用

TLDR;

LEFT OUTER JOINへのWHERE句の導入により、結合にINNER JOINの動作が与えられます

0
David Zehr