概要
GROUP BY 句 は レコードをグループ化することが出来ます。
HAVING 句 は グループ化したレコードに対して条件を指定出来ます。
グループ化というのは、例えば、学校でテスト結果を集計したテーブルがあったとします。これを学年別にグループ化して、平均値を求めたり、男女別にグループ化して、最高点数を求めるような場合に使用します。
グループ化したレコードに対して条件というのは、例えば、全教科のテストの平均点が30点以下のレコードを求めるような場合に使用します。
また、GROUP BY 句 と HAVING 句 は大抵の場合一緒に使われますが、必ずしも一緒に使う必要はありません。
内容
事前準備としてデータを用意します。
CREATE TABLE [dbo].[T1]( [ID] INT , [名前] NVARCHAR(30) , [誕生年] INT , [生没年] INT , [年号] NVARCHAR(10) , [性別] CHAR(2) , ) INSERT INTO T1([ID],[名前],[誕生年],[生没年],[年号],[性別]) VALUES (1,'芥川龍之介',1892 ,1927,'明治','男'), (2,'阿部公房',1924 ,1993,'大正','男'), (3,'有島武郎',1878 ,1923,'明治','男'), (4,'江戸川乱歩',1894 ,1965,'明治','男'), (5,'川端康成',1899 ,1972,'明治','男'), (6,'菊池寛',1888 ,1948,'明治','男'), (7,'司馬遼太',1923 ,1996,'大正','男'), (8,'太宰治',1909 ,1948,'明治','男'), (9,'樋口一葉',1872 ,1896,'明治','女'), (10,'与謝野 晶子',1878 ,1942,'明治','女'), (11,'向田 邦子',1929 ,1981,'昭和','女'), (12,'筒井 康隆',1934 ,null,'昭和','男') SELECT * FROM T1
ID | 名前 | 誕生年 | 生没年 | 年号 | 性別 |
1 | 芥川龍之介 | 1892 | 1927 | 明治 | 男 |
2 | 阿部公房 | 1924 | 1993 | 大正 | 男 |
3 | 有島武郎 | 1878 | 1923 | 明治 | 男 |
4 | 江戸川乱歩 | 1894 | 1965 | 明治 | 男 |
5 | 川端康成 | 1899 | 1972 | 明治 | 男 |
6 | 菊池寛 | 1888 | 1948 | 明治 | 男 |
7 | 司馬遼太 | 1923 | 1996 | 大正 | 男 |
8 | 太宰治 | 1909 | 1948 | 明治 | 男 |
9 | 樋口一葉 | 1872 | 1896 | 明治 | 女 |
10 | 与謝野 晶子 | 1878 | 1942 | 明治 | 女 |
11 | 向田 邦子 | 1929 | 1981 | 昭和 | 女 |
12 | 筒井 康隆 | 1934 | NULL | 昭和 | 男 |
誕生年が一番最近の年を男女別に取得する
SELECT MAX([誕生年]) AS 誕生年 FROM T1
誕生年 |
1934 |
これだと全レコードの中からの最近の年なので、GROUP BY 句 を使用して男女別に集計します。
SELECT [性別],MAX([誕生年]) AS 誕生年 FROM T1 GROUP BY [性別]
性別 | 誕生年 |
女 | 1929 |
男 | 1934 |
GROUP BY 句で指定した区分毎にまとめてからそれぞれのMAX値をとります。
もっと単純に性別が何種類あるかを確認します。
SELECT [性別] FROM T1 GROUP BY [性別]
性別 |
女 |
男 |
性別でまとめているのがわかります。これに集計関数のMAX を使って男女別に最高値を取得しています。GROUP BY 句 を使ったからと言って必ず、集計関数を使う必要はありません。
もっと、細かくグループ化することも出来ます。
男女別、年号別に誕生年が一番若い年を取得する
GROUP BY 句に 指定するカラムを2つにします。
SELECT [性別],[年号],MAX([誕生年]) AS 誕生年 FROM T1 GROUP BY [性別],[年号]
性別 | 年号 | 誕生年 |
女 | 昭和 | 1929 |
男 | 昭和 | 1934 |
男 | 大正 | 1924 |
女 | 明治 | 1878 |
男 | 明治 | 1909 |
より細かくグループ化出来ています。また、大正生まれの女性はいないのでレコードとしては出力されませんでした。
HAVING 句 の使い方
HAVING 句 は グループ化または、集計関数の結果に対して条件を指定出来ます。
WHERE 句 のように使うとエラーになります。
SELECT * FROM T1 HAVING [年号] = '昭和'
メッセージ 8121、レベル 16、状態 1、行 32 列 'T1.年号' は HAVING 句内では無効です。この列は集計関数または GROUP BY 句に含まれていません。
作家が2人以下の年号を求めるには下記のように年号別にグループ化してからHAVING 句 で条件を指定します。
SELECT [年号],COUNT(*) AS 人数 FROM T1 GROUP BY [年号] HAVING COUNT([年号]) <= 2
年号 | 人数 |
昭和 | 2 |
大正 | 2 |
HAVING 句はGROUP BY 句 とセットで使わなくてもいい
ほとんどの場合、HAVING 句は、GROUP BY 句 とセットで使います。使う場面は少ないでしょうが、一応セットで使わなくても構文としては、成立します。
SELECT 1 FROM T1 HAVING COUNT([年号]) = 12
コメント