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

9-63 導出テーブルを減らせ

SQLパズル

Accountsテーブル
acct_nbr
--------
       1
       2
       3
       4
       8

Fooテーブル            Barテーブル
acct_nbr  foo_qty      acct_nbr  bar_qty
--------  -------      --------  -------
       1       10             2      160
       2       20             3      320
       2       40             3      640
       3       80             3        1
       8      111             8      111
       8      222             8      222
       8      333             8      333

Accountsテーブルのacct_nbrに紐づく、foo_qtyの合計と
Accountsテーブルのacct_nbrに紐づく、bar_qtyの合計
を求める。

出力結果
acct_nbr  foo_qty_tot  bar_qty_tot
--------  -----------  -----------
       1           10            0
       2           60          160
       3           80          961
       4            0            0
       8          666          666

SQLパズル 第2版のパズル74 [導出テーブルを減らせ] を参考にさせていただきました


データ作成スクリプト

create table Accounts(acct_nbr number(1) primary key);

insert into Accounts values(1);
insert into Accounts values(2);
insert into Accounts values(3);
insert into Accounts values(4);
insert into Accounts values(8);

create table Foo(
acct_nbr number(1) references Accounts(acct_nbr),
foo_qty  number(3));

insert into Foo values(1, 10);
insert into Foo values(2, 20);
insert into Foo values(2, 40);
insert into Foo values(3, 80);
insert into Foo values(8,111);
insert into Foo values(8,222);
insert into Foo values(8,333);

create table Bar(
acct_nbr number(1) references Accounts(acct_nbr),
bar_qty  number(3));

insert into Bar values(2,160);
insert into Bar values(3,320);
insert into Bar values(3,640);
insert into Bar values(3,  1);
insert into Bar values(8,111);
insert into Bar values(8,222);
insert into Bar values(8,333);
commit;


SQL

--■■■インラインビューで外部結合する方法■■■
select aa.acct_nbr,foo_qty_tot,sum(nvl(c.bar_qty,0)) as bar_qty_tot
from (select a.acct_nbr,sum(nvl(b.foo_qty,0)) as foo_qty_tot
        from Accounts a Left Join Foo b
          on a.acct_nbr = b.acct_nbr
       group by a.acct_nbr) aa
Left Join Bar c
  on aa.acct_nbr = c.acct_nbr
group by aa.acct_nbr,foo_qty_tot
order by aa.acct_nbr;

--■■■union allを使う方法■■■
select a.acct_nbr,
sum(nvl(b.foo_qty,0)) as foo_qty_tot,
sum(nvl(b.bar_qty,0)) as bar_qty_tot
  from Accounts a
Left Join (select acct_nbr,foo_qty,0 as bar_qty from Foo
           union all
           select acct_nbr,0 as foo_qty,bar_qty from Bar) b
  on a.acct_nbr = b.acct_nbr
group by a.acct_nbr
order by a.acct_nbr;


解説

union allを使う方法が分かりやすいと思います。