トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
9-66 SQLで条件法
SQLパズル
Testテーブル
ID subject Val
--- ------- ---
100 math 100
100 English 80
100 science 80
200 math 80
200 science 95
300 math 40
300 English 90
300 science 55
400 math 80
500 science 30
700 science 30
700 null 20
mathが80以上かmathがない
かつ
Englishが50以上かEnglishがない
IDを求める。
出力結果
ID
---
100
200
400
500
700
データ作成スクリプト
create table Test(ID,subject,Val) as
select 100,'math' ,100 from dual union all
select 100,'English', 80 from dual union all
select 100,'science', 80 from dual union all
select 200,'math' , 80 from dual union all
select 200,'science', 95 from dual union all
select 300,'math' , 40 from dual union all
select 300,'English', 90 from dual union all
select 300,'science', 55 from dual union all
select 400,'math' , 80 from dual union all
select 500,'science', 30 from dual union all
select 700,'science', 30 from dual union all
select 700,null , 20 from dual;
SQL
--■■■2値論理の条件法(subjectのnullを考慮しない)を使う方法■■■
--select ID
-- from Test
--group by ID
--having min(case when (subject != 'math' or Val >= 80)
-- and (subject != 'English' or Val >= 50)
-- then 1 else 0 end) = 1;
--■■■3値論理の条件法(subjectのnullを考慮)を使う方法1■■■
select ID
from Test
group by ID
having min(case when lnnvl(subject='math') or Val >= 80
and lnnvl(subject='English') or Val >= 50
then 1 else 0 end) = 1;
--■■■3値論理の条件法(subjectのnullを考慮)を使う方法2■■■
select ID
from Test
group by ID
having min(case when Val >= 80 then 1
when subject='math' then 0 else 1 end)
* min(case when Val >= 50 then 1
when subject='English' then 0 else 1 end) = 1;
--■■■3値論理の条件法(subjectのnullを考慮)を使う方法3■■■
select ID
from Test
group by ID
having min(case when Val >= 80 then 1
when subject='math' then 0
when Val >= 50 then 1
when subject='English' then 0 else 1 end) = 1;
解説
2値論理の条件法か
3値論理の条件法かで、複雑さが大きく変わります。
条件法
PならばQは、
P is not true OR Q is true
だからです。
ちなみに、3値論理での、
P is not true OR Q is trueの真理値表は、下記となります。
T True
F False
U Unknown
P Q P is not true OR Q is true
- - --------------------------
T T T
T F F
T U U
F T T
F F T
F U T
U T T
U F T
U U T
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
lnnvl述語が使えないパターンの別例も考えてみましょう。
Aが10かつBが20なら、Cが30な行を出力
create table Not_Lnnvl(A,B,C) as
select 10, 20,30 from dual union all
select 10, 20,99 from dual union all
select 99, 20,30 from dual union all
select 99, 99,30 from dual union all
select 99, 99,99 from dual union all
select null, 99,99 from dual union all
select 99,null,99 from dual union all
select null,null,99 from dual;
select A,B,C
from Not_Lnnvl
where case when C=30 then 1
when A=10 and B=20 then 0
else 1 end = 1;
条件法PならばQは、
P is not true OR Q is true
となります。これをブール代数の交換法則により
Q is true OR P is not true
として、
Q is true を最初のwhen句で判断
次のP is not true
をelse句に遷移したかで判断してます。