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

7-63 勤務履歴の作成

SQLパズル

勤務履歴
 Sname  shift  qty  Sdate
------  -----  ---  ----------
 Smtih  AM      10  2006/03/20
 Smith  PM      20  2006/03/20
 Smith  PM      20  2006/03/21
Martin  AM      15  2006/03/20
Martin  PM      25  2006/03/20
Martin  AM      20  2006/03/21

Sname別、Sdate別の、勤務履歴を作成する。

出力順は、
小計の昇順、Sdateの昇順で、総合計は最後とする。

出力結果
 Sname  AM  PM  Total  Sdate
------  --  --  -----  ----------
 Smtih  10  20     30  2006/03/20
 Smtih   0  20     20  2006/03/21
 Smtih  10  40     50  小計
Martin  15  25     40  2006/03/20
Martin  20   0     20  2006/03/21
Martin  35  25     60  小計
総合計  45  65    110  総合計


データ作成スクリプト

create table 勤務履歴 as
select 'Smith' as Sname,'AM' as shift,10 as qty,
      to_date('2006/03/20','YYYY/MM/DD') as Sdate from dual
union select 'Smith' ,'PM',20,to_date('2006/03/20','YYYY/MM/DD') from dual
union select 'Smith' ,'PM',20,to_date('2006/03/21','YYYY/MM/DD') from dual
union select 'Martin','AM',15,to_date('2006/03/20','YYYY/MM/DD') from dual
union select 'Martin','PM',25,to_date('2006/03/20','YYYY/MM/DD') from dual
union select 'Martin','AM',20,to_date('2006/03/21','YYYY/MM/DD') from dual;


SQL

col Sname for a10
col AM for 99
col PM for 99
col Total for 99999
col Sdate for a10

--■■■方法1■■■
select case when 1 = all(grouping(Sname),grouping(Sdate))
       then '総合計' else Sname end as Sname,
sum(decode(shift,'AM',qty,0)) as AM,
sum(decode(shift,'PM',qty,0)) as PM,
sum(qty) as Total,
case when 1 = all(grouping(Sname),grouping(Sdate)) then '総合計'
     when grouping(Sdate) = 1 then '小計'
     else to_char(Sdate,'YYYY/MM/DD') end as Sdate
from 勤務履歴
group by RollUp(Sname,Sdate)
order by
decode(Sname,'総合計',1,0),
sum(Total) over(partition by Sname),
nullif(Sdate,'小計');

--■■■方法2■■■
select case when grouping(Sname) = 1
       then '総合計' else Sname end as Sname,
sum(decode(shift,'AM',qty,0)) as AM,
sum(decode(shift,'PM',qty,0)) as PM,
sum(qty) as Total,
case when grouping(Sname) = 1 then '総合計'
     when grouping(Sdate) = 1 then '小計'
     else to_char(Sdate,'YYYY/MM/DD') end as Sdate
from 勤務履歴
group by RollUp(Sname,Sdate)
order by
decode(Sname,'総合計',1,0),
sum(Total) over(partition by Sname),
nullif(Sdate,'小計');


解説

decode関数とクロス集計を組み合わせてます。

方法2では、RollUpを使った集計では、
grouping(Sname)=1 ならば grouping(Sdate)=1
が成立することを使ってます。