SQLのSELECT文でレコードをグループ化して検索(抽出)する GROUP BY

SQLのSELECT文でレコードをグループ化して検索(抽出)する GROUP BY

SQLではレコード(データ)を取得する際に、SELECTステートメントを使用します。

SQLのSELECT文でデータ(レコード)を取得(抽出)する
SQLを使用すると、データベースに対して様々な命令を与えることができます。データ(レコード)を抽出したり、データを追加・変更・削除したり、デ...

SELECTステートメントで取得するレコードは、テーブルに登録されているものになりますが、レコードを何らかの区分ごとにまとめた結果の値を取得したい場合があります。

例えば、従業員や学生などの人のデータを性別ごとにまとめて人数を取得する場合や、商品データをカテゴリーごとにまとめて売上金額を取得する場合などです。

そこで今回は、SELECTステートメントを使用してデータを取得する際に、特定の区分(列の値)をもとにグループ化する方法について紹介します。

データの取得に使用するサンプルテーブル

本記事では、データを取得するためのサンプルテーブルとして、以下のテーブルを使用します。

テーブル定義

サンプルテーブルは、学生情報を管理するための「学生」テーブルと、成績情報を管理するための「成績」テーブルを作成します。

学生テーブルには、学生情報を一意に判別するための主キー(プライマリーキー)となる「学籍番号」、氏名を管理するための「氏名」、学生の性別を管理する「性別(男性、女性)」の3つの列を作成します。

列名 データ型 主キー
学籍番号 int
氏名 nvarchar(10)
性別 nvarchar(2)

成績テーブルには、「学籍番号」、科目を管理する「科目(数学、英語)」、科目の得点を管理する「得点」の3つの列を作成します。

列名 データ型 主キー
学籍番号 int
科目 nvarchar(2)
得点 int

テーブルを作成するCREATE文のSQL

学生テーブルを作成するSQLは次のようになります。

成績テーブル作成するSQLは次のようになります。

テーブルにレコードを挿入するINSERT文のSQL

学生テーブルにはサンプルデータとして以下のレコードを挿入します。

成績テーブルにはサンプルデータとして以下のレコードを挿入します。

学生テーブル、成績テーブルへのデータのインサートは、複数のレコードを1回のSQLで一括挿入する形式で記述しています。
1回のINSERTで複数行のレコードをテーブルに一括で挿入する方法については、以下の記事を参照してください。

1回のINSERT(インサートSQL)で複数行のレコードを一括挿入(追加)する
SQLServerやMySQLなどのデータベースで、テーブルにレコードをINSERT文使用して追加するには、通常は以下のように記述します。 ...

レコードをグループ化する「GROUP BY」

SELECTステートメントで取得するレコードをグループ化する際は、「GROUP BY」というキーワードを使用します。

GROUP BYは、SELECTステートメントのFROM句の後に記述します。

GROUP BYの後には、グループ化する際のキーとなる列を指定します。

GROUP BYを使用して取得されるレコードは、GROUP BY句で指定したキー列の値が同じものが1件にまとめられます。

例えばチームという列に、Aという値を持つレコードが3つ、Bという値を持つレコードが2つ、Cという値を持つレコードが4つが登録されているテーブルからデータを取得する際にGROUP BYのキー列にチームを指定すると、A、B、Cの3レコードにまとめた結果が返されます。

以下では、作成したテーブルを使用して、GROUP BYを使用してデータを取得する例をいくつか紹介します。

学生の男女別の人数を取得する

学生テーブルのデータを男女別に取得して人数を算出するSQLは以下のようになります。

データの取得結果

性別 人数
女性 2
男性 3

GROUP BYのキー列に性別を指定することで、女性と男性のデータが取得されます。
GROUP BYでグループ化したレコードは集計関数で件数や合計などを取得することができます。
上記の例ではCOUNT関数を使用して、男女別の人数を取得しています。

参考資料 SQL Serverの集計関数

SQL Server 集計関数一覧
SQLServerで集計する際に使う主なSQL関数です。 合計を取得したい。 平均値を取得したい。 件数を取得したい。...

成績の科目別の最高点、最低点、平均点を取得する

成績テーブルのデータをから、科目別の最高点、最低点、平均点を取得するSQLは以下のようになります。

データの取得結果

科目 最高点 最低点 平均点
数学 95 59 76
英語 91 62 74

GROUP BYのキー列に科目を指定し、科目ごとの得点を分析するために、MAX関数で最高得点を、MIN関数で最低得点を、AVG関数で平均点を取得しています。

成績から男女別+科目別の最高点、最低点、平均点を取得する

最後に学生テーブルと成績テーブルを結合して、性別ごと(男女別)に各科目の最高点、最低点、平均点を取得する例を示します。

データの取得結果

性別 科目 最高点 最低点 平均点
女性 数学 95 77 86
男性 数学 85 59 70
女性 英語 83 63 73
男性 英語 91 62 75

学生テーブルと成績テーブルをINNER JOINで内部結合し、GROUP BYのキー列に性別と科目を指定して、男女別+科目別の最高点、最低点、平均点を取得しています。

補足

ここまでで、成績から科目別の得点を取得する例と、性別+科目別の得点を取得する例を別々に示しましたが、この2つのSQLをもとに1つの結果表として、男女別のそれぞれの得点と男女の合計を取得することも可能です。
2つのSQLを1つのSQLとして実行するためには、UNION句を使用します。

UNION句を使用して成績の得点データを取得するSQLは、以下のようになります。

データの取得結果

性別 科目 最高点 最低点 平均点
合計 数学 95 59 76
女性 数学 95 77 86
男性 数学 85 59 70
合計 英語 91 62 74
女性 英語 83 63 73
男性 英語 91 62 75