MySQLの左結合が無効であり、その使用方法今日SQLを書いていたとき、左結合を使用すると左のテーブルからすべてのデータが取得されないことに気づき、しばらく落ち込んでいました。後でよく調べたところ、常識的な間違いを犯していたことに気付きました(私は初心者です) これは元のSQLですこのクエリでは tb_line テーブル内のすべてのデータを取得できません。残念です... 後で、複数テーブルのクエリを実行すると、where ステートメントを実行する前に一時テーブルが形成されることを知りました。 オンは一時テーブルでの条件付きスクリーニングです。左結合を使用すると、条件が真であるかどうかに関係なく、左テーブルのデータが照会されます。条件が偽の場合は、null として表示されます。 一時テーブルが生成された後のフィルタリング条件はどこにありますか最初の図では、tb_vehicle テーブルのフィルター条件を where 句に指定しています。左結合によって生成された false 条件のデータは、where 句 v.del_flag='0' でフィルター処理されます (false 条件のデータでは del_flag が空であるため)。 ということで、左結合を使用したように見えますが、実際にはこのように記述した結果は、内部結合を使用した場合と同じになります。 正しい SQL は次のとおりです。一時テーブルでは、条件をフィルタリングして、左側のテーブルのデータを取得できます。 要約:左結合を使用して条件クエリを実行する必要がある場合は、条件フィルターを on の後に配置するか where の後に配置するかを慎重に検討する必要があります。 MySQL 左結合の落とし穴回避ガイド現象LEFT JOIN は、ブログの記事にコメントがいくつあるか、ショッピングモールの商品にコメントがいくつあるか、コメントにいいねがいくつあるかなど、MySQL を使用してクエリを実行するときに非常によく使用されます。ただし、join、on、where などのキーワードに馴染みがないために、クエリ結果が期待どおりにならない場合があります。そこで、今日はそれらをまとめて、落とし穴を回避できるようにします。 ここでシナリオを示し、2 つの質問をします。正しく答えられる場合は、この記事を読む必要はありません。 クラス管理アプリケーションがあり、すべてのクラスを格納するテーブル classes と、すべての生徒を格納するテーブル students があるとします。具体的なデータは次のとおりです。 クラスから * を選択; 学生から*を選択します。 現在、2 つの要件があります。
要件 1 については、ほとんどの人が何も考えずに次の 2 つの SQL の書き方を思いつくでしょう。どちらが正しいでしょうか。 c.name を選択し、count(s.name) を num として計算します。 クラスcから左の生徒sに参加 s.class_id = c.idの場合 かつ s.gender = 'F' c.name でグループ化 または c.name を選択し、count(s.name) を num として計算します。 クラスcから左の生徒sに参加 s.class_id = c.idの場合 ここで、s.gender = 'F' c.name でグループ化 要件 2 については、ほとんどの人が何も考えずに次の 2 つの SQL の書き方を思いつくでしょう。どちらが正しいでしょうか。 c.name を選択し、count(s.name) を num として計算します。 クラスcから左の生徒sに参加 s.class_id = c.idの場合 c.name = 'クラス 1' c.name でグループ化 または c.name を選択し、count(s.name) を num として計算します。 クラスcから左の生徒sに参加 s.class_id = c.idの場合 c.name = 'クラス 1' c.name でグループ化 下にスクロールしないでください。 !まずあなた自身の答えを述べてください。正解は下にあります。 〜 〜 〜 答えは、最初のステートメントが両方の要件に対して正しいということです。この問題を理解するには、次のセクションで詳しく説明する MySQL の左結合の実行原理を理解する必要があります。 ソースMySQL は、左結合を処理するためにネストされたループ アプローチを使用します。次のステートメントを例に挙げます。 LT LEFT から * を選択し、RT を P1(LT,RT) に結合します。P2(LT,RT) が P2(LT,RT) であるかどうかを確認します。 P1 は on フィルタ条件であり、存在しない場合は TRUE とみなされます。P2 は where フィルタ条件であり、存在しない場合は TRUE とみなされます。このステートメントの実行ロジックは次のように記述できます。 FOR each row lt in LT{// 左側のテーブルの各行を走査します BOOL b = FALSE; FOR RT の各行 rt で P1(lt, rt) を満たす場合、{// 右側のテーブルの各行を走査し、結合条件を満たす行を検索します。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 は最適化のためにバッファを使用し、行の比較回数を減らしますが、これはキー実行プロセスには影響せず、この記事の範囲外です。 この疑似コードから、次の 2 つの点がわかります。
2 つの要件に対するエラー ステートメントの実行結果とエラーの原因は次のとおりです。 要件 1 要件 2 要件 1: where 条件の右側のテーブルに対する制限により、データが欠落しています (クラス 4 の結果は 0 になるはずです) 要件 2 には、オン条件の左側の表の制限により冗長なデータがあります (他のクラスの結果も利用可能ですが、それでも間違っています) 要約する上記の問題現象と分析を通じて、結論を導き出すことができます。左結合ステートメントでは、左テーブル フィルターを where 条件に配置し、右テーブル フィルターを on 条件に配置する必要があります。そうすることで、結果が多すぎたり少なすぎたりすることなく、ちょうどよくなります。 SQL はシンプルに見えますが、実際には多くの詳細と原則が含まれています。少しの混乱で、期待どおりの結果にならない可能性があります。したがって、重要な瞬間に間違いを犯さないように、これらの詳細と原則に注意を払う必要があります。 上記は私の個人的な経験です。参考になれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
>>: CSS3 メディアクエリにおけるデバイス幅と幅の違いの詳細な説明
コンテンツオーバーフローとは何ですか?実際、テキストが大量にある場合、コンテンツ領域がそれだけの長さ...
序文開発プロセスにおいて、変数の定義は非常に頻繁かつ基本的なタスクです。変数の使用シナリオと範囲に応...
Alibaba ベクターアイコンライブラリにアクセスAlibaba ベクターアイコンライブラリ好き...
目次1. 概要2. Nginxインストールパッケージをダウンロードする3. 依存パッケージをインスト...
特記事項: Swoole 拡張機能のみがインストールされ、サーバーはホストにインストールされません。...
目次1. プロトタイプチェーン継承2. コンストラクタによる継承3. 組み合わせ継承4. プロトタイ...
序文コードを書く過程で、必然的にコードに何らかの変更を加えることになります。しかし、変更を加えるとき...
目次1: 単一マシンのパスワードフリーログイン構成1. 仮想マシンのホスト名を設定する2. 仮想マシ...
必要Windows システムでも Linux システムでも、さまざまな理由でパスワードを忘れてしまう...
目次1. axiosをインストールする2. アクシオスの使用1.ホームページでaxiosを参照する2...
MySQLトリガーの簡単な例文法CREATE TRIGGER <トリガー名> -- トリ...
序文開発プロセスでは、10 進データ型がよく使用されます。 MySQL では、小数点は正確なデータ型...
目次1. クエリ結果を挿入する2. 集計クエリ2.1 はじめに2.2 集計関数2.3 group b...
1. CSS の概念: (カスケーディング スタイル シート)利点: 1. コンテンツとプレゼンテ...
Nginx をインストールして試してみましょう。画像はクラスであり、コンテナはオブジェクトであること...