4

次の表を検討してください。

mysql> select * from phone_numbers;
+-------------+------+-----------+
| number      | type | person_id |
+-------------+------+-----------+
| 17182225465 | home |         1 |
| 19172225465 | cell |         1 |
| 12129876543 | home |         2 |
| 13049876543 | cell |         2 |
| 15064223454 | home |         3 |
| 15064223454 | cell |         3 |
| 18724356798 | home |         4 |
| 19174335465 | cell |         5 |
+-------------+------+-----------+

自宅の電話は持っているが携帯電話を持っていない人を探しています。

このクエリは機能します:

mysql> select h.*
    -> from phone_numbers h
    -> left join phone_numbers c
    -> on h.person_id = c.person_id
    -> and c.type = 'cell'
    -> where h.type = 'home'
    -> and c.number is null;
+-------------+------+-----------+
| number      | type | person_id |
+-------------+------+-----------+
| 18724356798 | home |         4 |
+-------------+------+-----------+

しかし、これはしません:

mysql> select h.*
    -> from phone_numbers h
    -> left join phone_numbers c
    -> on h.person_id = c.person_id
    -> and h.type = 'home'
    -> and c.type = 'cell'
    -> where c.number is null;
+-------------+------+-----------+
| number      | type | person_id |
+-------------+------+-----------+
| 19172225465 | cell |         1 |
| 13049876543 | cell |         2 |
| 15064223454 | cell |         3 |
| 18724356798 | home |         4 |
| 19174335465 | cell |         5 |
+-------------+------+-----------+

2 つの唯一の違いは、h.type = 'home'条件の場所です。最初の場合はwhere句内にあり、2 番目の場合は句の一部ですon

2 番目のクエリが最初のクエリと同じ結果を返さないのはなぜですか?

4

5 に答える 5

6

2 番目の SQL では、条件 h.type = 'home' は外部結合条件の一部であり、結果に対するフィルターではありません。h.type='cell' であるすべてのレコードについて、条件 h.type = 'home' が FALSE であるため、「一致する」c 行が見つからないため、c.number は null であり、これが唯一のフィルタリング (WHERE) 条件です。 .

疑似コードでは、2 番目の SQL は次のように機能します。

for each row in phone_numbers h /* Note this is ALL home AND cell phones */
   select c.number from phone_numbers c
   where h.person_id = c.person_id
   and h.type = 'home'
   and c.type = 'cell';
   if c.number is null (i.e. no row found)
     display h.*
   end if
end loop;
于 2008-12-05T15:16:51.027 に答える
2

左結合を行うとき、私はこのように物事にアプローチします。結合では、2つのテーブルを実際にリンクするannyフィールドと、結合の右側(結合の2番目のテーブル)からのフィルタリング条件を指定する必要があります(1つの例外を除いて、すぐに説明します)。結合(1番目のテーブル)の左側からのフィルタリング条件は、where句に含める必要があります。そうしないと、見たとおりに(そして、Tonyが非常にうまく説明したように)結合に誤った影響を及ぼします。結合の右側がwhere句にある必要があるのは、そのテーブルでnull値(つまり、最初のテーブルにはあるが2番目のテーブルにはないレコード)を探している場合だけです。

于 2008-12-05T15:30:22.403 に答える
-2

これで問題が解決するかどうかはわかりませんが...

「and」で始まるステートメントは、ON 句の一部ではなく、WHERE 句の一部である必要があります。ON 句には、テーブルの結合に使用される列に関するステートメントのみを含める必要があります。

于 2008-12-05T15:15:09.890 に答える