トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

10-198 existsとforallとunique

SQLパズル

CodeTable
Code  Val
----  ---
AAAA    2
AAAA    4
AAAA    6
BBBB    1
BBBB    3
CCCC    2
CCCC    3
CCCC    4
DDDD    1
DDDD    2

Codeごとで、以下を満たすかのブール値を取得する。
exists_1  少なくとも1つのValが、2の倍数である
exists_2  少なくとも1つのValが、2の倍数でない
forall_1  全てのValが、2の倍数である
forall_2  全てのValが、2の倍数でない
unique_1  ただ1つのValが2の倍数である
unique_2  ただ1つのValが2の倍数でない

出力結果
Code  exists_1  exists_2  forall_1  forall_2  unique_1  unique_2
----  --------  --------  --------  --------  --------  --------
AAAA         1         0         1         0         0         0
BBBB         0         1         0         1         0         0
CCCC         1         1         0         0         0         1
DDDD         1         1         0         0         1         1

こちらを参考にさせていただきました(英語)
データベース実践講義を参考にさせていただきました


データ作成スクリプト

create table CodeTable(Code,Val) as
select 'AAAA',2 from dual union
select 'AAAA',4 from dual union
select 'AAAA',6 from dual union
select 'BBBB',1 from dual union
select 'BBBB',3 from dual union
select 'CCCC',2 from dual union
select 'CCCC',3 from dual union
select 'CCCC',4 from dual union
select 'DDDD',1 from dual union
select 'DDDD',2 from dual;


SQL

select Code,
max(case when mod(Val,2) = 0 then 1 else 0 end) as exists_1,
max(case when mod(Val,2) = 0 then 0 else 1 end) as exists_2,
min(case when mod(Val,2) = 0 then 1 else 0 end) as forall_1,
min(case when mod(Val,2) = 0 then 0 else 1 end) as forall_2,
case sum(case when mod(Val,2) = 0 then 1 else 0 end) when 1 then 1 else 0 end as unique_1,
case sum(case when mod(Val,2) = 0 then 0 else 1 end) when 1 then 1 else 0 end as unique_2
from CodeTable
group by Code
order by Code;


解説

uniqueは、sumで数えるといいでしょう。
case式が2つある時は、単純case式と検索case式を混ぜると分かりやすいと思います。

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
存在肯定命題  (少なくとも1つのXが、2の倍数である)
存在否定命題  (少なくとも1つのXが、2の倍数でない)
全称肯定命題  (全てのXが、2の倍数である)
全称否定命題  (全てのXが、2の倍数でない)
は、それぞれ

存在肯定命題  max(case when mod(Val,2) = 0 then 1 else 0 end)  (少なくとも1つのXが、2の倍数である)
存在否定命題  max(case when mod(Val,2) = 0 then 0 else 1 end)  (少なくとも1つのXが、2の倍数でない)
全称肯定命題  min(case when mod(Val,2) = 0 then 1 else 0 end)  (全てのXが、2の倍数である)
全称否定命題  min(case when mod(Val,2) = 0 then 0 else 1 end)  (全てのXが、2の倍数でない)
となります。

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
変換公式をメモしておきましょう。

全称 → min
存在 → max

肯定 → (case when 条件 then 1 else 0 end)
否定 → (case when 条件 then 0 else 1 end)

まとめると
全称肯定命題なら min(case when 条件 then 1 else 0 end) = 1
全称否定命題なら min(case when 条件 then 0 else 1 end) = 1
存在肯定命題なら max(case when 条件 then 1 else 0 end) = 1
存在否定命題なら max(case when 条件 then 0 else 1 end) = 1

真なら1、偽なら0にしておくことにより、ブール値としても使えます。