集計関数の小ネタ

SQL Server Advent Calendar 23日目 です。

今日は集計関数の小ネタです。 集計関数 (Transact-SQL)

Null を無視する

大体の集計関数は、Null を無視します。Null でも含めるのは、count(*) 位かな?
こんなテーブルとデータがあった時に

create table [成績] ( 
  [テスト] nvarchar(10), 
  [名前] nvarchar(10), 
  [点数] int
)

insert into [成績] ( [テスト], [名前], [点数] ) values
 ( '国語', '田中', 75 ), 
 ( '国語', '佐藤', 80 ), 
 ( '国語', '鈴木', 89 ), 
 ( '算数', '佐藤', 80 ), 
 ( '算数', '鈴木', 98 ), 
 ( '算数', '西岡', 65 ), 
 ( null, null, null )
go
select 
  count(*) as [全件] -- 7
  , count([点数]) as [点数の件数] -- 6 
  , sum([点数]) as [点数の合計] -- 481
  , avg([点数]) as [点数の平均] -- 481 / 6 = 80
  , avg(isnull([点数], 0)) as [点数の平均2] -- 481 / 7 = 68
from 
  [成績]


データが無い場合や、全ての値が Null の時は、Null を返します。

select sum([点数]) -- null
from [成績] 
where [点数] > 100
-- where [点数] is null -- この条件でも null が返る。

重複を無視する

重複を無視する場合は、distinct を指定する。

select 
  count(distinct [テスト]) as [テストの種類] -- 2
  , count(distinct [名前]) as [受講者の人数] -- 4
  , sum(distinct [点数]) as [重複除いた点数合計] -- 401
from 
  [成績]

Over を付けて Window 関数

大体は、ORDER BY 句 (Transact-SQL) と一緒に使うと思いますが、OVER 句 (Transact-SQL) を使うこともできます。

-- group by を使って、テスト毎の最高点/最低点/平均点を表示
select 
  [テスト] 
  , max([点数]) as [最高点] 
  , min([点数]) as [最低点] 
  , avg([点数]) as [平均点]
from 
  [成績] 
where 
  [テスト] is not null 
group by 
  [テスト] 
-- over (partition by) を使って、受講者の点数と(テスト毎の)平均点との差を表示
select 
  [テスト] 
  , [名前] 
  , [点数] 
  , avg([点数]) over (partition by [テスト]) as [平均点] 
  , [点数] - avg([点数]) over (partition by [テスト]) as [平均点との差]
from 
  [成績] 
where 
  [テスト] is not null