トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
10-277 model句とgrouping sets
SQLパズル
PJTable
ID dept code1 code2 cost
-- ---- ------ ----- ----
1 1111 200904 22222 300
2 1111 200905 22222 200
3 1111 200905 88888 600
4 1111 200905 88888 -200
5 2222 200904 66666 300
6 2222 200905 66666 200
7 2222 200905 77777 600
8 2222 200905 77777 -200
dept,code1ごとのcostの集計行を追加する。
集計行のIDとcode2は、null
集計行のIsSumは、yes
とする。
dept,code1ごとのIDも、sumIDとして求める。
出力結果
ID dept code1 code2 cost sumID IsSum
---- ---- ------ ----- ---- ----- -----
1 1111 200904 22222 300 1 no
null 1111 200904 null 300 1 yes
2 1111 200905 22222 200 2 no
3 1111 200905 88888 600 2 no
4 1111 200905 88888 -200 2 no
null 1111 200905 null 600 2 yes
5 2222 200904 66666 300 3 no
null 2222 200904 null 300 3 yes
6 2222 200905 66666 200 4 no
7 2222 200905 77777 600 4 no
8 2222 200905 77777 -200 4 no
null 2222 200905 null 600 4 yes
データ作成スクリプト
create table PJTable(ID,dept,code1,code2,cost) as
select 1,'1111','200904','22222', 300 from dual union
select 2,'1111','200905','22222', 200 from dual union
select 3,'1111','200905','88888', 600 from dual union
select 4,'1111','200905','88888',-200 from dual union
select 5,'2222','200904','66666', 300 from dual union
select 6,'2222','200905','66666', 200 from dual union
select 7,'2222','200905','77777', 600 from dual union
select 8,'2222','200905','77777',-200 from dual;
SQL
--■■■model句を使う方法(10g以降)■■■
select id,dept,code1,code2,cost,sumID,IsSum
from PJTable
model
partition by(dept,code1,
dense_rank() over(order by dept,code1) as sumID)
dimension by(ID)
measures(code2,Cost,cast('no' as varchar2(3)) as IsSum)
rules(cost [null] = sum(cost)[any],
IsSum[null] = 'yes')
order by dept,code1,ID;
--■■■grouping setsを使う方法■■■
select ID,dept,code1,code2,sum(cost) as cost,
dense_rank() over(order by dept,code1) as sumID,
decode(grouping(ID),1,'yes','no') as IsSum
from PJTable
group by grouping sets((ID,dept,code1,code2),
(dept,code1))
order by dept,code1,ID;
--■■■複合列指定のrollupを使う方法■■■
select ID,dept,code1,code2,sum(cost) as cost,
dense_rank() over(order by dept,code1) as sumID,
decode(grouping(ID),1,'yes','no') as IsSum
from PJTable
group by dept,code1,rollup((ID,code2))
order by dept,code1,ID;
解説
grouping setsは、縦に並べて記述すると分かりやすいのです。
group by grouping sets((ID,dept,code1,code2),
(dept,code1))
複合列指定のrollupを使ってもいいです。
10-301 rollupで複合列(Composite Columns)指定
model句で、位置参照によるupsertを使うのも有力でしょう。
10-275 model句で集計行を追加