厄介なNULL
「NULL」とは列に設定する値が未定の時に時折使用される印(マーカー)です。
「NULL」に対しては比較演算子などが使用できないので注意が必要です。
目次
1. はじめに
ここでは、商品テーブル(Shouhin)を使ってNULLの取り扱いを見てみましょう。
まずは、Shouhinの内容を下のSQLでデータを確認してください。
SELECT
*
FROM
Shouhin
WHERE
shouhin_id=26
OR
shouhin_id=27
shouhin_id | name | name_kana | category_id | price |
---|---|---|---|---|
26 | セット商品 | せっとしょうひん | 4000 | |
27 | セット商品2 | せっとしょうひん2 | 3000 |
セット商品を2種類売り出そうとShouhinテーブルに登録しましたが、商品カテゴリが決まっていないため、とりあえず商品カテゴリに「NULL」を設定してある状態です。
この2商品のcategory_idと「NULL」が入っていますが、目には見えません。(ピンクの部分)
この「NULL」入りデータに対して比較演算子を使ってみます。
2. NULLに対しての比較演算子
category_idが1は野菜、2は果物です。
野菜でも果物でもない商品を下のSQLで取得してみます。
SELECT
*
FROM
Shouhin
WHERE
category_id <> 1 AND category_id <> 2
shouhin_id | name | name_kana | category_id | price |
---|
セット商品とセット商品2は、野菜でも果物でもないはずなのに、なにも取得できませんでした。
では、これはどうでしょう?
category_idがNULLと等しいものを取得しようとしています。
SELECT
*
FROM
Shouhin
WHERE
category_id = NULL
shouhin_id | name | name_kana | category_id | price |
---|
こちらも上と同じく、なにも取得できませんでした。
これは、「NULL」に対しては、比較演算子が無効なことを意味します。
「NULL」に対しては比較演算子が使えないことがわかりました。
では、「NULL」のデータを捕まえるにはどのようにしたらいいでしょう?
3. IS NULLとIS NOT NULL
「IS NULL」と「IS NOT NULL」を使うと「NULL」を捕まえることができます。
3-1. IS NULL
「商品カテゴリがNULL」という条件を指定するには下のようにします。
SELECT
*
FROM
Shouhin
WHERE
category_id IS NULL
shouhin_id | name | name_kana | category_id | price |
---|---|---|---|---|
26 | セット商品 | せっとしょうひん | 4000 | |
27 | セット商品2 | せっとしょうひん2 | 3000 |
これで、category_idがNULLの商品を取得できました。
3-2. IS NOT NULL
「NOT」を使って「商品カテゴリがNULLではない」という条件も指定できます。
SELECT
*
FROM
Shouhin
WHERE
category_id IS NOT NULL
shouhin_id | name | name_kana | category_id | price |
---|---|---|---|---|
1 | アスパラガス | あすぱらがす | 1 | 256 |
2 | かぼちゃ | かぼちゃ | 1 | 300 |
3 | キャベツ | きゃべつ | 1 | 128 |
・ ・ ・ |
category_idがNULLの商品は取得されていません。
4. NULLに対しての演算
ここでは、簡単のためSELECTのみで演算をしてみます。
単純に「1+10」の計算結果を表示するSQLです。
※実は、SELECTはFROMでテーブルを指定しなくても使えます。
SELECT 1+10
1+10 |
---|
11 |
では、「NULL」に対して計算を施してみます。
SELECT NULL+10
1+10 |
---|
計算結果は、「NULL」です。
「NULL」は「未定」なので、「未定+10」の答えも「未定(NULL)」となるわけです。
計算式の中に「NULL」が紛れ込んでいるとその答えは「NULL」になるので注意が必要です。
5. 集約関数でのNULLの取り扱われ方
Shouhinテーブルのpriceに「NULL」が紛れ込んでいた場合、集約関数の結果も「NULL」になるのでしょうか?
5-1. 合計値を求める
SELECT SUM( price ) FROM Shouhin
NULLは無視されて(無いものとして)合計値が計算される。
5-2. 最大値を求める
SELECT MAX( price ) FROM Shouhin
NULLは無視されて(無いものとして)最大値が取得される。
5-3. 最小値を求める
SELECT MIN( price ) FROM Shouhin
NULLは無視されて(無いものとして)最小値が取得される。
5-4. 平均値を求める
SELECT AVG( price ) FROM Shouhin
NULLは無視されて(無いものとして)平均値が計算される。
5-5. データ件数を求める
SELECT COUNT( price ) FROM Shouhin
priceがNULLの行はカウントされない。
テーブルの全行数を求めるつもりで「COUNT( price )」を使ってもpriceがNULLの行はカウントされないので注意が必要です。
確実に、テーブルの全行数を求めるには、「COUNT( * )」を使いましょう。
COUNTの動作を試す場合は、NULLが2件紛れ込んでいるcategory_idを使ってみてください。
SELECT COUNT( category_id ) FROM Shouhin
SELECT COUNT( * ) FROM Shouhin
2件の差があることが確認できます。
6. まとめ
「NULL」は「未定」を表す印(マーカー)です。
「NULL」に対しては、比較演算子が使えません。
「NULL」を捉えるには、「IS NULL」もしくは、「IS NOT NULL」を使用します。
また、「NULL」に対する演算の答えはいつも「NULL」になります。
「NULL」を許容しているテーブルについては、列に対しての条件指定や演算に注意が必要です。
集約関数SUM、MAX、MIN、AVGは、指定された列値のNULLを無視(無いものと)して計算した結果を返します。
集約関数COUNTは、指定された列値にNULLを持つ行を省いた行数を返します。
SQLを書く前に、テーブルのどの列がNULLを許容しているか確認しておくといいと思います。
ちなみに、練習用テーブルで、NULLを許容しているのは、Shouhinテーブルのcategory_id列のみです。
次は、「INとBETWEEN」についてです。