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

9-35 count関数の引数にRowID

SQLパズル

fishesテーブル
sampleID  fish    num
--------  ------  ---
   A      minnow   10
   A      pike     20
   B      carp     40
   B      pike     60
   C      carp     70
   D      carp     80
   D      minnow   90
   D      pike     30

WaterGroupsテーブル
WaterGroupID  descript     sampleID
------------  -----------  --------
           1  muddy water     A
           1  muddy water     B
           2  fresh water     A
           2  fresh water     C
           2  fresh water     D
           3  salt water      B

WaterGroupIDごとの、
numの平均(小数点以下を四捨五入)を列挙する

出力結果
WaterGroupID  descript     fish    numAvg
------------  -----------  ------  ------
           1  muddy water  carp        20  ← ( 0+40)/2
           1  muddy water  minnow       5  ← (10+ 0)/2
           1  muddy water  pike        40  ← (20+60)/2
           2  fresh water  carp        50  ← ( 0+70+80)/3
           2  fresh water  minnow      33  ← (10+ 0+90)/3
           2  fresh water  pike        17  ← (20+ 0+30)/3
           3  salt water   carp        40
           3  salt water   minnow       0
           3  salt water   pike        60

SQLパズル(日本語版)のパズル38 [魚を数える] を参考にさせていただきました
SQLパズル 第2版のパズル42 [魚のサンプリング調査] を参考にさせていただきました


データ作成スクリプト

create table fishes(
sampleID char(1),
fish     varchar2(6),
num      number(2),
primary key(sampleID,fish));

insert into fishes values('A','minnow',10);
insert into fishes values('A','pike'  ,20);
insert into fishes values('B','carp'  ,40);
insert into fishes values('B','pike'  ,60);
insert into fishes values('C','carp'  ,70);
insert into fishes values('D','carp'  ,80);
insert into fishes values('D','minnow',90);
insert into fishes values('D','pike'  ,30);

create table WaterGroups(
WaterGroupID number(1),
descript     varchar2(11),
sampleID     char(1),
primary key(WaterGroupID,sampleID));

insert into WaterGroups values(1,'muddy water','A');
insert into WaterGroups values(1,'muddy water','B');
insert into WaterGroups values(2,'fresh water','A');
insert into WaterGroups values(2,'fresh water','C');
insert into WaterGroups values(2,'fresh water','D');
insert into WaterGroups values(3,'salt water' ,'B');
commit;


SQL

--■■■count関数の引数にRowIDを使う方法■■■
select b.WaterGroupID,b.descript,a.fish,
round(sum(decode(b.sampleID,a.sampleID,a.num,0))/count(distinct b.RowID)) as numAvg
  from fishes a,WaterGroups b
group by b.WaterGroupID,b.descript,a.fish
order by b.WaterGroupID,a.fish;

--■■■count関数の引数にRowIDを使わない方法■■■
select b.WaterGroupID,b.descript,a.fish,
round(sum(decode(b.sampleID,a.sampleID,a.num,0))/count(distinct b.sampleID)) as numAvg
  from fishes a,WaterGroups b
group by b.WaterGroupID,b.descript,a.fish
order by b.WaterGroupID,a.fish;


解説

count関数の引数にRowIDを使って、
結合元のレコード数を求めてます(WaterGroupsを結合の駆動表と考えてます)