MySQLのLEFT JOINピット回避ガイド
げんしょう
ここで私はまず1つのシーンを提供して、2つの問題を投げ出して、もしあなたがその文章に答えることができたら、読む必要はありません.
クラス管理アプリケーションがあり、テーブルclassesがあり、すべてのクラスが保存されていると仮定します.すべての学生を保存した表studentsがあります.具体的なデータは以下の通りです(廖雪峰のオンラインSQLに感謝します).
では、2つのニーズがあります.クラスごとの名称とそれに対応する女子生徒数を探し出す クラスを見つけた人の総数 需要1については、多くの人が考えずに次の2つのsqlの書き方を考え出すことができますが、どちらが正しいですか?
または
需要2に対して、多くの人も考えずに次の2つのsqlの書き方を考え出すことができますが、どちらが正しいですか?
または
下にひっくり返さないでください!!まず自分の答えを出して、正しい答えは下にあります.......答えは両方とも第一の文が正しいということですが、この問題を明らかにするには、mysqlが
ルーツ
mysqlは
このうち
もちろん、実際にはMySQLはbuffer方式で最適化され、ローの比較回数が減少しますが、重要な実行プロセスには影響しません.本明細書では説明しません.
この擬似コードから、2つの点がわかります.右の表を制限したい場合は必ず ない場合
次の2つの要件のエラー文の実行結果とエラーの原因を展開します:要件1
需要2デマンド1 where条件で右表が制限されているためデータが欠落している(四班では 需要2 on条件で左の表に制限があるためデータが余っている(他のクラスの結果も出ているが、間違っている) まとめ
以上の問題現象と分析から,
SQLは简単に见えて、実は多くの细部の原理が中にあって、1つの小さい混同は结果が予想と一致しないことをもたらして、だからふだんこれらの细部の原理に注意して、肝心な时に间违いを避けます.
left join
mysqlを使って検索する過程でよく見られることです.例えば、ブログの文章に何件のコメントがあるか、ショッピングモールの商品に何件のコメントがあるか、1件のコメントに何人のコメントがあるかなどです.しかしjoin
・on
・where
・などのキーワードに慣れていないため、検索結果が予想に合わない場合があるので、今日はまとめて、一緒にピットを避けていきます.ここで私はまず1つのシーンを提供して、2つの問題を投げ出して、もしあなたがその文章に答えることができたら、読む必要はありません.
クラス管理アプリケーションがあり、テーブルclassesがあり、すべてのクラスが保存されていると仮定します.すべての学生を保存した表studentsがあります.具体的なデータは以下の通りです(廖雪峰のオンラインSQLに感謝します).
SELECT * FROM classes;
id name
1
2
3
4
SELECT * FROM students;
id class_id name gender
1 1 M
2 1 F
3 1 M
4 1 F
5 2 F
6 2 M
7 2 M
8 3 F
9 3 M
10 3 F
では、2つのニーズがあります.
SELECT c.name, count(s.name) as num
FROM classes c left join students s
on s.class_id = c.id
and s.gender = 'F'
group by c.name
または
SELECT c.name, count(s.name) as num
FROM classes c left join students s
on s.class_id = c.id
where s.gender = 'F'
group by c.name
需要2に対して、多くの人も考えずに次の2つのsqlの書き方を考え出すことができますが、どちらが正しいですか?
SELECT c.name, count(s.name) as num
FROM classes c left join students s
on s.class_id = c.id
where c.name = ' '
group by c.name
または
SELECT c.name, count(s.name) as num
FROM classes c left join students s
on s.class_id = c.id
and c.name = ' '
group by c.name
下にひっくり返さないでください!!まず自分の答えを出して、正しい答えは下にあります.......答えは両方とも第一の文が正しいということですが、この問題を明らかにするには、mysqlが
left join
の実行原理について、次の節で展開することを理解しなければなりません.ルーツ
mysqlは
left join
のネストループのような方法でスレーブ処理を行い、以下の文を例に挙げます.SELECT * FROM LT LEFT JOIN RT ON P1(LT,RT)) WHERE P2(LT,RT)
このうち
P1
Yeson
フィルタ条件、欠落はTRUE
、P2
Yeswhere
フィルタ条件、欠落もTRUE
、この文の実行ロジックは以下のように記述できる.FOR each row lt in LT {//
BOOL b = FALSE;
FOR each row rt in RT such that P1(lt, rt) {// , join
IF P2(lt, rt) {// where
t:=lt||rt;// ,
}
b=TRUE;// lt RT
}
IF (!b) { // RT, lt RT , null
IF P2(lt,NULL) {// null where
t:=lt||NULL; // lt null
}
}
}
もちろん、実際にはMySQLはbuffer方式で最適化され、ローの比較回数が減少しますが、重要な実行プロセスには影響しません.本明細書では説明しません.
この擬似コードから、2つの点がわかります.
on
条件で行い、where
で行うとデータが欠落してしまい、左の表が右の表で一致行がない行が最終結果に出なくなる可能性があり、私たちのleft join
に対する理解に反します.左の表に右の表がない行については、右の表の後b=FALSE
を遍歴するので、NULL
右の表を足し合わせようとしますが、このとき私たちのP2
右の表の行には制限があり、NULLがP2
(NULL
一般的には制限条件を満たさないので、IS NULL
このような場合を除く)では、最終的な結果には入れません.結果が欠落します.where
条件は、on
条件が左テーブルに対してどのような制限を加えても、左テーブルの各行に少なくとも1行の合成結果があり、左テーブル行に対して右テーブルに対応する行がなければ、右テーブル遍歴終了後b=FALSE
1行NULL
でデータが生成されるが、このデータは余計である.したがって、左のテーブルをフィルタするにはwhereを使用する必要があります.次の2つの要件のエラー文の実行結果とエラーの原因を展開します:要件1
name num
2
1
2
需要2
name num
4
0
0
0
0
の結果があるはず)以上の問題現象と分析から,
left join
文では左表フィルタはwhere条件,右表フィルタはon条件でなければならず,結果は少なく,ちょうどいいと結論した.SQLは简単に见えて、実は多くの细部の原理が中にあって、1つの小さい混同は结果が予想と一致しないことをもたらして、だからふだんこれらの细部の原理に注意して、肝心な时に间违いを避けます.