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

4-18 日本語の条件文にドモルガンの法則

SQLパズル

mainT
a_code  b_code  a_suuchi  b_suuchi  c_code  d_code  kbn
------  ------  --------  --------  ------  ------  ---
    10      xx         1        10  b       xx01     99  ←加算対象外
    10      xx         1        10  a       xx01     99  ←加算対象外
    10      yy        10       100  b       yy01     99  ←加算対象外
    10      yy        10       100  a       yy01     99  ←加算対象外
    10      xx       100      1000  b       xx02     99
    10      yy       100      1000  a       yy02     99
    10      xx        50       500  b       xx02     10
    10      xx        50       500  a       xx02     10
    10      xx        80       800  b       xx02     20
    10      yy        80       800  a       yy02     20
    10      yy        60       600  b       yy03     30
    10      yy        40       400  a       yy03     30
    20      xx         1        10  b       xx01     99  ←加算対象外
    20      xx         1        10  a       xx01     99  ←加算対象外
    20      yy        10       200  b       yy01     99
    20      yy        10       100  a       yy01     99
    50      xx       111       123  a       xx01     22
    50      yy       333       123  b       xx01     22

subT
d_code  kbn
------  ---
xx01     99
yy01     99
xx02     99
yy02     99
xx03     99
yy03     99

a_codeごとの、
b_codeがxxのa_suuchiの合計
b_codeがyyのa_suuchiの合計
b_suuchiの合計
を求める。

ただし、
mainTのa_code,d_codeが等しい中での、c_codeがaのb_suuchiの合計と
mainTのa_code,d_codeが等しい中での、c_codeがbのb_suuchiの合計が等しい。
かつ、
subTに、dcodeとkbnが同じデータが存在すれば
加算対象としない。

出力結果
A_CODE  a_suuchiの計(xx)  a_suuchiの計(yy)  b_suuchiの計
------  ----------------  ----------------  ------------
    10               280               280          5600
    20                 0                20           300
    50               111               333           246

こちらを参考にさせていただきました


データ作成スクリプト

create table mainT(a_code,b_code,a_suuchi,b_suuchi,c_code,d_code,kbn) as
select 10,'xx',  1,  10,'b','xx01',99 from dual union all
select 10,'xx',  1,  10,'a','xx01',99 from dual union all
select 10,'yy', 10, 100,'b','yy01',99 from dual union all
select 10,'yy', 10, 100,'a','yy01',99 from dual union all
select 10,'xx',100,1000,'b','xx02',99 from dual union all
select 10,'yy',100,1000,'a','yy02',99 from dual union all
select 10,'xx', 50, 500,'b','xx02',10 from dual union all
select 10,'xx', 50, 500,'a','xx02',10 from dual union all
select 10,'xx', 80, 800,'b','xx02',20 from dual union all
select 10,'yy', 80, 800,'a','yy02',20 from dual union all
select 10,'yy', 60, 600,'b','yy03',30 from dual union all
select 10,'yy', 40, 400,'a','yy03',30 from dual union all
select 20,'xx',  1,  10,'b','xx01',99 from dual union all
select 20,'xx',  1,  10,'a','xx01',99 from dual union all
select 20,'yy', 10, 200,'b','yy01',99 from dual union all
select 20,'yy', 10, 100,'a','yy01',99 from dual union all
select 50,'xx',111, 123,'a','xx01',22 from dual union all
select 50,'yy',333, 123,'b','xx01',22 from dual;

create table subT(d_code,kbn) as
select 'xx01',99 from dual union all
select 'yy01',99 from dual union all
select 'xx02',99 from dual union all
select 'yy02',99 from dual union all
select 'xx03',99 from dual union all
select 'yy03',99 from dual;


SQL

select a_code,
sum(case b_code when 'xx' then a_suuchi else 0 end) as "a_suuchiの計(xx)",
sum(case b_code when 'yy' then a_suuchi else 0 end) as "a_suuchiの計(yy)",
sum(b_suuchi) as "b_suuchiの計"
from (select a_code,b_code,a_suuchi,b_suuchi,d_code,kbn,
      sum(case c_code when 'a' then b_suuchi else 0 end)
      over(partition by a_code,d_code) as sumXX,
      sum(case c_code when 'b' then b_suuchi else 0 end)
      over(partition by a_code,d_code) as sumYY
        from mainT) a
 where sumXX != sumYY
    or not exists(select 1 from subT b
                   where b.d_code = a.d_code
                     and b.kbn    = a.kbn)
group by a_code
order by a_code;


解説

mainTのa_code,d_codeが等しい中での、c_codeがaのb_suuchiの合計と
mainTのa_code,d_codeが等しい中での、c_codeがbのb_suuchiの合計が等しい。
かつ、
subTにdcodeとkbnが同じデータが存在すれば
加算対象としない。

全ての要素は、加算対象か、加算対象でないかの
どちらかであることをふまえて、ドモルガンの法則を適用してます。

加算対象となる条件は、
mainTのa_code,d_codeが等しい中での、c_codeがaの場合のb_suuchiの合計と
mainTのa_code,d_codeが等しい中での、c_codeがbの場合のb_suuchiの合計が同じ等しくない、
または、
subTにdcodeとkbnが同じデータが存在しない

-------------------------------------------------------------------------------------
後は、加算対象となる条件をwhere句で使って、行にフィルタをかけてます。