SQLで真理値表を表示

SQLで真理値表を表示する方法について記述します。

SQLでと言いつつ、postgresqlでしか試していませんのでご注意ください。

2値論理

with truth_tables as (
    select true tv
    union all
    select false
)

select
    tt1.tv t1,
    tt2.tv t2,
    tt1.tv and tt2.tv land,
    tt1.tv or tt2.tv lor
from truth_tables tt1, truth_tables tt2
;

実行結果

 t1 | t2 | land | lor 
----+----+------+-----
 t  | t  | t    | t
 t  | f  | f    | t
 f  | t  | f    | t
 f  | f  | f    | f
(4 rows)

いわゆる普通の真理値表を返します。

3値論理

with truth_tables as (
    select true tv
    union all
    select false
    union all
    select null
)

select
    tt1.tv t1,
    tt2.tv t2,
    tt1.tv and tt2.tv land,
    tt1.tv or tt2.tv lor,
    tt1.tv = tt2.tv eq
from truth_tables tt1, truth_tables tt2
;

実行結果

 t1 | t2 | land | lor | eq 
----+----+------+-----+----
 t  | t  | t    | t   | t
 t  | f  | f    | t   | f
 t  |    |      | t   | 
 f  | t  | f    | t   | f
 f  | f  | f    | f   | t
 f  |    | f    |     | 
    | t  |      | t   | 
    | f  | f    |     | 
    |    |      |     | 
(9 rows)

true,false以外にnullを取りうる3値論理版です。 ポイントは何と言ってもnullでしょう。特にnull=nullnullになることに注意が必要です。この事実を知らないと、下記のようなSQLを書きがちです。

select * from hoge_tables where a = 1 and b = 2 and c = null and d = 4;

このSQLを書いた人はカラムaが1、bが2、cがnull、dが4である行を取得することを期待してると思いますが、c = nullを満たすようなことはないために思い通りに取得できなくなってしまいます。null比較は専用の演算があります。

select * from hoge_tables where a = 1 and b = 2 and c is null and d = 4;

nullの比較にはイコールでなくis nullを使うということはよく説明されてるように思います。 何故そのようなことをする必要があるかをSQLにおける論理演算を通して理解するのも良いかと思います。

おまけ

is nullも真理値表に組み込みたいと思って、下記のようにするとエラーになりました。

select
    tt1.tv is tt2.tv t1_is_t2
from truth_tables tt1, truth_tables tt2
;

「そりゃそうか」と思いましたが、次に「いや、これだとis nullだけじゃなくてis trueも考えることになる。そもそもis trueなんてあるのか?」という疑問が浮かび上がってきました。 試してみます。

select true is true;

実行結果

 ?column? 
----------
 t
(1 row)

あるやんけ。 調べてみると、参考[3]の通り、{expression} is [true|false|null]などの構文があるようです(つまり{expression} is {expression}はダメ)。

null以外であれば、普通にイコール比較すれば良いので、is trueとis falseの使いどころはいまいち分からないですね...

参考

[1] https://www.postgresql.org/docs/13/datatype-boolean.html

[2] https://www.postgresql.org/docs/13/functions-logical.html

[3] https://www.postgresql.org/docs/13/functions-comparison.html