トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
8-16 2ヶ月前のデータも出力
SQLパズル
AmountTable2
Code yyyymm amount
---- ------ ------
AAAA 200701 100
AAAA 200702 200
AAAA 200704 400
AAAA 200711 500
AAAA 200712 600
AAAA 200801 700
AAAA 200802 800
AAAA 200810 900
BBBB 200705 111
BBBB 200707 222
BBBB 200712 333
BBBB 200801 444
BBBB 200802 555
同じCodeで、
yyyymmddが2ヶ月前のamount(なければ0)を出力する。
AmountTable2のプライマリキーは、Codeとyyyymmとする。
出力結果
Code yyyymm amount amount2monthsBefore
---- ------ ------ -------------------
AAAA 200701 100 0
AAAA 200702 200 0
AAAA 200704 400 200
AAAA 200711 500 0
AAAA 200712 600 0
AAAA 200801 700 500
AAAA 200802 800 600
AAAA 200810 900 0
BBBB 200705 111 0
BBBB 200707 222 111
BBBB 200712 333 0
BBBB 200801 444 0
BBBB 200802 555 333
データ作成スクリプト
create table amountTable2(
Code char(4),
yyyymm char(6),
amount number(3),
primary key(Code,yyyymm));
insert into amountTable2 values('AAAA','200701',100);
insert into amountTable2 values('AAAA','200702',200);
insert into amountTable2 values('AAAA','200704',400);
insert into amountTable2 values('AAAA','200711',500);
insert into amountTable2 values('AAAA','200712',600);
insert into amountTable2 values('AAAA','200801',700);
insert into amountTable2 values('AAAA','200802',800);
insert into amountTable2 values('AAAA','200810',900);
insert into amountTable2 values('BBBB','200705',111);
insert into amountTable2 values('BBBB','200707',222);
insert into amountTable2 values('BBBB','200712',333);
insert into amountTable2 values('BBBB','200801',444);
insert into amountTable2 values('BBBB','200802',555);
commit;
SQL
--■■■相関サブクエリを使う方法■■■
select Code,yyyymm,amount,
nvl((select b.amount
from AmountTable2 b
where b.Code = a.Code
and b.yyyymm = case substr(a.yyyymm,-2)
when '01' then to_char(to_number(a.yyyymm) - 100 -1+11)
when '02' then to_char(to_number(a.yyyymm) - 100 -2+12)
else to_char(to_number(a.yyyymm)-2)
end),0) as "amount2monthsBefore"
from AmountTable2 a;
--■■■分析関数を使う方法■■■
select Code,yyyymm,amount,
nvl(max(amount) over(partition by Code
order by to_number(substr(yyyymm,1,4))*12+to_number(substr(yyyymm,-2))
Range between 2 Preceding and 2 Preceding),0) as "amount2monthsBefore"
from amountTable2;
--■■■interval型を使う方法■■■
select Code,yyyymm,amount,
nvl(max(amount)
over(partition by Code
order by to_date(yyyymm,'yyyymm')
range between interval '2' month preceding
and interval '2' month preceding),0) as "amount2monthsBefore"
from AmountTable2;
解説
分析関数を使う方法では、
yyyymmを12進数に変換して、order by句で使ってます。
12進数変換の例
200710 → 2007*12+10
200711 → 2007*12+11
200712 → 2007*12+12
200801 → 2008*12+ 1=2007*12+13
200802 → 2008*12+ 2=2007*12+14
ちなみに、計算式の結果は、下記となります。
2007*12+10 = 24094
2007*12+11 = 24095
2007*12+12 = 24096
2008*12+ 1 = 24097
2008*12+ 2 = 24098