今回はPostgreSQLのIS NULLとIS NOT NULLを使い、NULLかどうかで行を絞り込みます。取得したデータの意味を整理します。
所要時間は15分ほどです。
それでは、さっそく始めていきましょう!
今日のテーマと到達目標
NULLは値がないことを表します。数値の0や、長さ0の文字列である空文字列とは異なります。
今回は、次の2つの条件を使い分けることが目標です。
| 条件 | 意味 |
|---|---|
列名 IS NULL |
その列がNULLの行を対象にする |
列名 IS NOT NULL |
その列がNULLではない行を対象にする |
NULLの判定には、= NULLではなくIS NULLを使います。値が入力されている行を探すときは、IS NOT NULLを使います。
今回使うテーブルと列
取得元はmobility.poisです。mobilityがスキーマ名、poisが施設を格納するテーブル名です。1行が1施設を表します。
| 列名 | 意味 |
|---|---|
poi_id |
施設を識別するID |
poi_name |
施設名 |
closed_date |
閉業日を表す日付の列 |
今回確認するのは、closed_dateに日付が入っているか、NULLなのかという違いです。NULLになっている理由や、施設が現在営業しているかどうかまで、この判定だけで決めることはできません。
演習①:NULLの行を取得する
閉業日がNULLの施設を、施設IDの昇順で最大10件取得しました。
SELECT poi_id, poi_name, closed_date
FROM mobility.pois
WHERE closed_date IS NULL
ORDER BY poi_id
LIMIT 10;
実行結果では、施設IDが1から10までの10行が表示されました。closed_dateはどの行も空欄でした。
| poi_id | poi_name | closed_dateの値 |
|---|---|---|
| 1 | Tokyo_station_001 | NULL |
| 2 | Shinjuku_shopping_002 | NULL |
| 3 | Shibuya_restaurant_003 | NULL |
| 4 | Ikebukuro_cafe_004 | NULL |
| 5 | Yokohama_office_005 | NULL |
| 6 | Kawasaki_park_006 | NULL |
| 7 | Omiya_hotel_007 | NULL |
| 8 | Kichijoji_entertainment_008 | NULL |
| 9 | Tokyo_station_009 | NULL |
| 10 | Shinjuku_shopping_010 | NULL |
表のNULLは、画面の空欄が表す値を説明するために記載しています。実行画面にNULLという文字が表示されていたわけではありません。
空欄表示と空文字列を混同しない
psqlの表示設定によっては、NULLが空欄で表示されます。今回の行はclosed_date IS NULLという条件で取得しているため、表示が空欄でもNULLだと確認できます。
以前の演習で表示していた[NULL]も、NULLを見分けるための表示でした。表示の文字が変わっても、それだけで保存された値が変わったことにはなりません。
また、今回のLIMIT 10は表示件数の上限です。10行表示されたことから、NULLの行がテーブル全体で10行しかないとはいえません。
「閉業日の日付が入力されている施設は、この結果に含まれるか」という確認には、「含まれません」と回答しました。日付の入った行はIS NULLの条件を満たさないためです。
演習②:NULLではない行を取得する
次に、条件をIS NOT NULLに変更しました。
SELECT poi_id, poi_name, closed_date
FROM mobility.pois
WHERE closed_date IS NOT NULL
ORDER BY poi_id
LIMIT 10;
実行結果は次の4行でした。
| poi_id | poi_name | closed_date |
|---|---|---|
| 39 | Omiya_hotel_039 | 2020-02-24 |
| 41 | Tokyo_station_041 | 2023-09-26 |
| 45 | Yokohama_office_045 | 2028-05-02 |
| 46 | Kawasaki_park_046 | 2022-04-28 |
最大10件を指定していますが、条件に合う行が4行だったため、表示されたのは4行です。LIMIT 10は必ず10行を出す指定ではありません。
「閉業日がNULLの施設は、この結果に含まれるか」という確認にも、「含まれません」と回答しました。IS NOT NULLでは、NULLの行が除外されます。
日付の有無と日付の範囲は別の条件
今回の結果には2028-05-02も含まれています。IS NOT NULLは日付が入っていることを判定し、その日付が過去か未来かは判定しません。
そのため、この結果をそのまま「すでに閉業した施設の一覧」と言い換えることはできません。今回のSQLで確認したのは、閉業日を表す列に日付が入っている施設です。
列の名前、値の有無、日付の範囲を分けて読むと、SQLの結果を正確に説明できます。
合格条件と学習記録
| 確認項目 | 確認できた内容 |
|---|---|
| NULLの行を取得できる |
IS NULLを使い、施設ID1〜10の10行を取得 |
| 日付のある行を除外する条件だと理解する | 演習①で日付のある施設は含まれないと回答 |
| NULLではない行を取得できる |
IS NOT NULLを使い、日付のある4行を取得 |
| NULLを除外する条件だと理解する | 演習②でNULLの施設は含まれないと回答 |
2つのSQLと確認への回答を通じて、NULLかどうかによる絞り込みを確認できました。今回の演習はSELECTによる取得であり、保存されたデータは更新していません。
まとめ
NULLの行はIS NULL、NULLではない行はIS NOT NULLで取得します。空欄という見た目だけで空文字列だと判断せず、取得条件と表示設定を確認します。
日付が入っていることと、その日付が特定の期間に入ることは別です。SQLで指定した条件に沿って、取得結果の意味を説明することが大切です。