SQLでSELECT文を実行した結果として、データの重複が起こっている場合、重複を解消した状態で結果として表示したいといったケースは意外と多いものです。
今回は重複データをまとめる際に利用出来る「DISTINCT」と「GROUP BY」の使い方についてサンプルを交えながらご紹介していきたいと思います。


SQLで重複データをまとめる方法1: DISTINCT
1つ目の重複データをまとめる方法として「DISTINCT」を利用することが可能です。
DISTINCTは、データベースから指定した条件のデータを取得する過程で重複データの削除を行います。
データベース用語では、テーブルから特定のデータを取得することを「射影」と呼ぶため、射影の過程で重複データを削除しているとも言えます。
基本構文
DISTINCTはSELECT句に記述します。
- SELECT DISTINCT(カラム名)[, カラム名, ...] FROM テーブル名;
DISTINCTは基本的に1つのカラムに対してのみ使用することが可能です。
例外として下記のようにCOUNT関数などの内部であれば、複数カラムにDISTINCTを利用することは可能です。
- SELECT COUNT(DISTINCT(カラム名)), COUNT(DISTINCT(カラム名)) FROM テーブル名;
サンプル
では実際にDISTINCTを使ったサンプルSQL文で動きを確認していきましょう。
今回はサンプルテーブルに下記を用意しました。
memberテーブル
- +------+-----------------+------------+
- | id | name | team_name |
- +------+-----------------+------------+
- | 1 | 田中さとし | チーム1 |
- | 2 | 鈴木あきら | チーム2 |
- | 3 | 斉藤ゆうき | チーム3 |
- | 4 | 伊藤つよし | チーム2 |
- | 5 | 有坂たろう | チーム1 |
- | 6 | 増田ゆうた | チーム1 |
- +------+-----------------+------------+
基本パターン
DISTINCTを使ってチーム名の重複を削除した結果を出力してみましょう。
- SELECT DISTINCT(team_name) FROM member;
実行した結果は下記の通りです。
- +------------+
- | team_name |
- +------------+
- | チーム1 |
- | チーム2 |
- | チーム3 |
- +------------+
複数カラムの指定
次に複数カラムを指定した場合の動きを確認してみます。
- SELECT DISTINCT(team_name), name FROM member;
実行した結果は下記の通りです。
- +------------+-----------------+
- | team_name | name |
- +------------+-----------------+
- | チーム1 | 田中さとし |
- | チーム2 | 鈴木あきら |
- | チーム3 | 斉藤ゆうき |
- | チーム2 | 伊藤つよし |
- | チーム1 | 有坂たろう |
- | チーム1 | 増田ゆうた |
- +------------+-----------------+
チーム名をDISTINCTしていても、名前が異なるため重複データとは認識されません。
チーム名と名前が全く同じデータが存在する場合には、該当データの重複が削除された結果が表示されます。
COUNT関数で件数を取得
COUNT関数と併用してDISTINCTを利用した際の動きを確認してみましょう。
- SELECT COUNT(DISTINCT(team_name)) FROM member;
実行した結果が下記の通りです。
- +----------------------------+
- | COUNT(DISTINCT(team_name)) |
- +----------------------------+
- | 3 |
- +----------------------------+
上述したようにDISTINCTは射影の時点で重複データを削除するため、最終的にカウントされる件数は重複データを削除した後の件数となります。
SQLで重複データをまとめる方法2: GROUP BY
SQLで重複データをまとめるもうひとつの方法として「GROUP BY」を利用することが可能です。
GROUP BYでは、条件に一致するデータを一旦グループ化して全て取り出し、同一グループから1つのデータだけを表示します。
射影の過程でデータを排除するのではなく、一度該当データを全て抽出している点が異なります。
基本構文
GROUP BYの基本構文は下記の通りです。
- SELECT カラム名[, カラム名, ...]
- FROM テーブル名
- [WHERE 条件式]
- GROUP BY カラム名[, カラム名, ...];
GROUP BY句は複数カラムを指定することも可能です。
サンプル
GROUP BY句のサンプルでも、DISTINCTのサンプルで利用した「member」テーブルを活用します。
基本パターン
- SELECT team_name
- FROM member
- GROUP BY team_name;
実行した結果が下記の通りです。
- +------------+
- | team_name |
- +------------+
- | チーム1 |
- | チーム2 |
- | チーム3 |
- +------------+
DISTINCTで指定した場合と同じ結果となりましたね。
COUNT関数で件数を取得
GROUP BYで指定したカラムに対して、COUNT関数を適用し結果を確認してみましょう。
- SELECT COUNT(team_name), team_name
- FROM member
- GROUP BY team_name;
実行した結果が下記の通りです。
- +------------------+------------+
- | COUNT(team_name) | team_name |
- +------------------+------------+
- | 3 | チーム1 |
- | 2 | チーム2 |
- | 1 | チーム3 |
- +------------------+------------+
このようにCOUNTを指定した際、GROUP BYでは重複データを射影時に排除しているわけではないため、それぞれのグループ化したデータ毎の件数が結果として表示されます。


さいごに:重複データをまとめるSQL文は用途によって使い分けよう!
本記事では、重複データをまとめるSQL文として「DISTINCT」と「GROUP BY」の使い方についてご紹介してきました。
COUNT関数使用時の例でも挙げた通り、同じような処理に見えて実際には内部で異なる処理が行われています。
ご自身の用途に適しているのはどちらかを判断して、重複データをまとめるSQL文を記述するようにしましょう。