1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQLの三値論理

1
Posted at

今回はPostgreSQLの三値論理を学びます。NULLを含む条件がどのように判定されるかを確認し、取得したデータの意味を整理します。

所要時間は15分ほどです。
それでは、さっそく始めていきましょう!

用語と今回扱う対象

三値論理は、条件の判定をTRUE・FALSE・UNKNOWNの3種類で扱う仕組みです。

用語 意味
TRUE(真) 条件が成り立つ
FALSE(偽) 条件が成り立たない
UNKNOWN(不明) 条件が成り立つか判定できない

今回扱う対象はSQLの条件式と、その判定結果です。PostgreSQLではUNKNOWNを真偽値型のNULLで表します。NULLは空文字列やゼロとは異なります。

演習で確認するのは、SELECTで表示される判定結果と、WHEREで取得される行です。統計的な推定は行いません。

WHEREで残るのはTRUEの行だけ

WHEREは、条件がTRUEになった行を取得します。FALSEの行だけでなく、UNKNOWNの行も取得しません。

WHEREの条件の判定結果 取得対象になるか
TRUE なる
FALSE ならない
UNKNOWN ならない

FALSEとUNKNOWNは異なる判定結果ですが、WHEREで取得されないという点は共通しています。

演習①:3種類の判定を表示する

次のSQLを実行しました。

SELECT
    1 = 1 AS true_result,
    1 = 2 AS false_result,
    NULL = 1 AS unknown_result;

実行画面には、順にt、f、空欄が表示されました。

列名 画面の表示 判定結果
true_result t TRUE
false_result f FALSE
unknown_result 空欄 UNKNOWNを表すNULL

1 = 1は成り立ち、1 = 2は成り立ちません。一方、NULL = 1では比較する値が不明なため、等しいとも等しくないとも判定できません。

「WHEREの条件がUNKNOWNになった行は含まれるか」という質問には、「含まれません」と回答しました。

NULLの表示を見分ける

psqlでは、次の設定でNULLの表示を変更できます。

\pset null '[NULL]'

これは表示設定であり、保存された値を変更しません。今回送った実行画像ではNULLは空欄で表示されていました。設定コマンドの実行結果は画像で確認していないため、設定済みとは扱いません。

演習②:UNKNOWNをNOTで否定する

次に、それぞれの条件にNOTを付けました。

SELECT
    NOT (1 = 1) AS not_true,
    NOT (1 = 2) AS not_false,
    NOT (NULL = 1) AS not_unknown;

実行結果は、順にf、t、空欄でした。

否定前 NOTを付けた判定結果
TRUE FALSE
FALSE TRUE
UNKNOWN UNKNOWN

TRUEとFALSEは反転しますが、UNKNOWNはUNKNOWNのままです。値が不明である以上、等しいかどうかを否定しても判定は確定しません。

「NOT (NULL = 1)はどれになるか」という確認には、UNKNOWNの意味で回答しました。入力は「NNKNOWN」でしたが、文脈からUNKNOWNの回答として確認しました。

演習③:施設データで確認する

取得元はmobility.poisです。1行が1施設を表し、poi_idは施設ID、poi_nameは施設名、closed_dateは閉業日を表す日付の列です。

次のSQLを実行しました。

SELECT poi_id, poi_name, closed_date
FROM mobility.pois
WHERE NOT (closed_date = DATE '2023-09-26')
ORDER BY poi_id;

実行結果は次の3行でした。

poi_id poi_name closed_date
39 Omiya_hotel_039 2020-02-24
45 Yokohama_office_045 2028-05-02
46 Kawasaki_park_046 2022-04-28

日付が入力されており、その日付が2023年9月26日と等しくない行が取得されています。この条件は過去の日付だけを指定するものではないため、2028年の日付も含まれます。

NULLの施設が含まれない理由

条件の判定を、日付の値ごとに分けて確認します。

closed_dateの値 指定日と等しいか NOTを付けた結果 WHEREで取得
2023-09-26 TRUE FALSE されない
2020-02-24など、指定日以外の日付 FALSE TRUE される
NULL UNKNOWN UNKNOWN されない

前の演習で確認した施設ID41の閉業日は2023年9月26日なので、今回は含まれません。また、NULLの施設も含まれません。除外される理由は同じではなく、前者はFALSE、後者はUNKNOWNになるためです。

最後の確認では、「NULLと日付の比較はUNKNOWNになり、NOTを付けてもUNKNOWNのままで、WHEREでは取得されないから」という選択肢を選びました。

NOTは条件を否定するものであり、NULLを日付に書き換える操作ではありません。NULLの行そのものを探す場合は、前回学んだIS NULLを使います。

入力途中のSQLを取り消す

演習中に、入力をいったんクリアする方法も確認しました。

入力途中のSQLを取り消すにはControl + Cを使います。通常の入力状態では、次のpsqlコマンドでも入力バッファをリセットできます。

\r

引用符を閉じ忘れた場合はControl + Cを使います。これらは入力途中のSQLを取り消す操作で、保存済みのデータを削除するものではありません。

合格条件と学習記録

確認項目 確認できた内容
3種類の判定結果を確認する TRUE・FALSE・UNKNOWNのSELECTを実行
WHEREの取得条件を理解する UNKNOWNの行は含まれないと回答
NOTとUNKNOWNの関係を理解する 否定後もUNKNOWNと回答
施設データで説明する 3行の取得結果を確認し、NULLが除外される理由を選択

まとめ

WHEREで取得されるのは、条件がTRUEになった行だけです。NULLを含む通常の等値比較はUNKNOWNとなり、NOTを付けてもUNKNOWNのままです。

条件を否定すればNULLの行も取得できる、と考えないことが今回の要点です。NULLかどうかを調べる条件と、日付の値を比較する条件を区別して使います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?