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

4-10 合計が2位以内のデータを取得

SQLパズル

金額テーブル
key1  key2  money
----  ----  -----
A     A1       10
A     A1       20
A     A1       30
A     A2      120
B     B1       50
B     B1       60
B     B1       70
B     B2       10
B     B2       30
B     B3       70
C     C1       20
C     C2       20
C     C3       20
C     C4       10
C     C5        0

key1ごとに、
key2ごとのmoneyの合計が2位以内(Denseな順位)のデータの、
moneyの合計を出力する

出力結果
key1  key2  money
----  ----  -----
A     A2      120
A     A1       60
B     B1      180
B     B3       70
C     C1       20
C     C2       20
C     C3       20
C     C4       10
こちらを参考にさせていただきました


データ作成スクリプト

create table 金額(
key1  char(1),
key2  char(2),
money number(3));

insert into 金額 values('A','A1', 10);
insert into 金額 values('A','A1', 20);
insert into 金額 values('A','A1', 30);
insert into 金額 values('A','A2',120);
insert into 金額 values('B','B1', 50);
insert into 金額 values('B','B1', 60);
insert into 金額 values('B','B1', 70);
insert into 金額 values('B','B2', 10);
insert into 金額 values('B','B2', 30);
insert into 金額 values('B','B3', 70);
insert into 金額 values('C','C1', 20);
insert into 金額 values('C','C2', 20);
insert into 金額 values('C','C3', 20);
insert into 金額 values('C','C4', 10);
insert into 金額 values('C','C5',  0);
commit;


SQL

--■■■分析関数を使う方法■■■
select key1,key2,money
  from (select key1,key2,sum(money) as money,
        dense_rank() over(partition by key1 order by sum(money) desc) as Rank
          from 金額
         group by key1,key2)
where Rank <= 2
order by key1,Rank,key2;

--■■■相関サブクエリを使う方法■■■
select key1,key2,sum(money) as money
  from 金額 a
 group by key1,key2
having (select count(distinct sum(b.money))+1
          from 金額 b
         where b.key1=a.key1
         group by b.key2
        having sum(b.money) > sum(a.money)) <= 2
order by key1,money desc,key2;


解説

dense_rank関数を使って、
sum関数の結果に対して順位付けする方法のほうが、
SQLがシンプルになってます