2011-07-29 9 views
6

これはとても基本的なようですが、私はより良い言葉の不足のために大変です。私は2つのテーブルを持っている、のは千数百recondsが各テーブルにalbumsartistsNullとIN()は予期せぬ結果をもたらします

CREATE TABLE `albums` (
    `album_id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `artist_id` bigint(20) DEFAULT NULL, 
    `name` varchar(200) NOT NULL, 
    PRIMARY KEY (`album_id`) 
) 
CREATE TABLE `artists` (
    `artist_id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `name` varchar(250) NOT NULL, 
    PRIMARY KEY (`artist_id`) 
) 

あり、それらを呼びましょう。アルバムの行の一部がnull artist_idであることが予想されます。しかし

、私はアルバムなしのアーティストを見つけるために、次のクエリを実行する場合:

SELECT * FROM artists WHERE artist_id NOT IN (SELECT artist_id FROM albums)

は...クエリはゼロ結果を返します。私はこれが真実ではないことを知っています。

SELECT * FROM artists WHERE artist_id NOT IN (SELECT artist_id FROM albums WHERE artist_id IS NOT NULL)

...と私は戻って数千行を取得:だから私はこの1つを試してみました。私の質問です:なぜ最初のクエリは、任意の数値= NULLという考え方で動作しているようですか?または、NULLがIN()ステートメントで奇妙な結果になっていますか?私はこれが私が逃した基本的なものだと感じています。私は通常、dbテーブルではNULLを使用しません。

答えて

7

NOT EXISTS

SELECT * FROM artists ar 
WHERE NOT EXISTS 
    (SELECT * FROM albums al WHERE ar.artist_id = al.artist_id) 

ロジック意味的に正しい理由がある:

  • NOT IN (x, y, NULL)が実際
      NOT (x OR y OR NULL)
    • あるが実際
      • (NOT x) AND (NOT y) AND (NOT NULL)
      • であります

のでNULLは、それがSQL NULLのが解釈される方法に関係しています全体NOT IN

+0

NOT EXISTSのように思えますが、やや速かったです。情報をありがとう! –

7

クイックアンサー - INステートメントは=a OR =b OR ...のショートカットです。このリストにnullを含めると、文が壊れていると思います。あなたの2番目のオプションは、おそらくより良い選択肢です。

また、結合を使用しても効果的です。

+0

true OR unknownはtrueと評価されます。そして、それはNOT INです:違ったブレークダウン – gbn

2

を無効にする - あなたはUNKNOWN値と考える必要があります。

は、あなたが次のことを実行する場合は、= 1

をartist_idしているとしましょう:

artist_id = NULL 

よりもむしろ '偽' を取得 - あなたは '不明' を取得。

あなたのようなクエリを実行すると、 'TRUE'と評価される値だけが返されます。

artist_id IN (NULL, NULL, NULL...) = UNKNOWN 
artist_id NOT IN (NULL, NULL, NULL....) = UNKNOWN 
+0

十分に公正ですが、私はレトルトしますが、なぜヌルを使うのですか?これは私のデータベース設計でしたが、アーティストがいないときはnullの代わりに0を使用していました。代わりにnullを使用する理由は何ですか? –

+0

間違いなく議論の余地があります。私は個人的に便利なプレースホルダとして使用しています。空白の値(つまり ''、n/aなど)を常に設定する必要はなく、多くの未知フィールドが頻繁にあるテーブルをロードする場合は、一貫してNULLを使用します。私はこの方法に満足しています - しかし、この悪い習慣を考慮する人もいます。 – chris

+2

@Chrisでは、プレースホルダ値を使用すると、データを見る人はどの値がプレースホルダであるかを知る必要があるため、より混乱すると主張する人もいます。合理的なプレースホルダ値が選択できない設計が常に存在するため、普遍的な解決策にはなりません。また、NULLを使用することには実用上のメリットもあります。テーブルとインデックスの両方でストレージを必要としないため、パフォーマンスも向上します。 –

関連する問題