4

このトピックについて、ここやインターネット上で多くのスレッドが作成されていることを知っています。しかし、私は 2 つのステートメントの違いに関する最終的なポイントを得ることができません! つまり、試行錯誤を繰り返して、クエリで必要なすべての結果に到達できますが、実際にはナイフを完全に制御することはできません!

私は自分自身を非常に優れたプログラマーであり、非常に優れた SQL-ista だと考えていますが、これについて少し恥ずかしい思いをしています...

次に例を示します。

  • Web サイトのページ ("web_page") を含むテーブルがあります。
  • カテゴリを含むテーブル (「カテゴリ」)。
  • カテゴリには 1 つまたは複数のページを含めることができますが、その逆はできません
  • カテゴリにはページがまったく含まれていない可能性があります
  • Web サイトでページを表示することも、しないこともできます

したがって、すべてのカテゴリとそのページを表示したい場合は、ページのあるカテゴリとないカテゴリの両方を意味し、次のようにする必要があります。

FROM category
LEFT JOIN web_page ON ( web_page.category_id = category.category_id AND web_page.active = "Y" )

したがって、カテゴリにページがない場合、そのカテゴリのレコードに web_page_id NULL が表示されます。

しかし、もしそうなら:

FROM category
LEFT JOIN web_page ON ( web_page.category_id = category.category_id )
...
WHERE web_page.active = "Y"...

少なくとも 1 つの web_page を持つカテゴリのみを選択します...しかし、なぜですか?

これはほんの一例でした… この違いを一度は理解しておきたい!

ありがとうございました。

4

3 に答える 3

4

クエリを意図したとおりに機能させるには、条件をON句に入れます。

FROM category
LEFT JOIN web_page ON web_page.category_id = category 
   and web_page.active = "Y"

これが機能する理由は、(すべてではありませんがほとんどのデータベースで)行が結合されたWHEREに句が行をフィルター処理するためです。結合によって Web ページの行が結合されない場合 (カテゴリに Web ページがなかったため)、Web ページのすべての列は になり、値 ( など) と aの比較はすべてfalse になるため、非-結合行は除外されます。null"Y"null

ただし、条件をON句に移動すると、結合が行われるときに条件が実行されるため、結合される行のみが結合active = "Y"されますが、そのような行がない場合は、左の結合nullWeb ページが取得されます。

このバージョンのクエリは、「すべてのカテゴリとアクティブなWeb ページ (存在する場合)を教えてください」と言っています。

「ほとんどのデータベース」と言ったことに注意してください...たとえば、mysqlはあなたが何をしようとしているのかを理解するのに十分スマートであり、mysqlで実行するとクエリが意図したとおりに機能します。

于 2012-07-04T13:04:51.007 に答える
1

これは、SQL が段階的に処理されているために発生します。

  1. FROM節 (すべての結合はここにあります);
  2. WHERE句;
  3. GROUP BY句;
  4. ウィンドウ関数 (MySQL とは関係ありませんが);
  5. ORDER BY句。

したがって、フィルタリングしたい場合、web_page.active='Y'または同じ条件で結合したい場合、これは本当に重要です。OUTER前者の場合、結合が完了し、結果を除外して、結合を1 つに変換しますINNER。後者の場合、一致しない行がNULL対応する列の値になるため、目的の結果が得られます。

于 2012-07-04T13:08:44.713 に答える
0

理解の部分であなたを助けようとしています。

LEFT JOINは、条件が 内で指定されている場合、照合するレコードを検索するときに適用されるSQL 言語のファセットです。下部の WHERE 句で条件を指定すると、結合が発生した後、すべてのレコードに適用されます。LEFT JOINこれには、ご覧のように を anに変更するという意図しない副作用がありINNER JOINます。

WHERE次のような節を実行することで、これを回避できます。

WHERE COALESCE(web_page.active,"Y") = "Y"

しかし、それは実際には同じ結果になるとは限りません。したがって、それを行う適切な方法は、その基準ONJOIN.

于 2012-07-04T13:09:54.627 に答える