DISTINCTの使い方及び、GROUP BYとの違いについて

はじめに
SQLで重複を排除する際に使用される「DISTINCT」。本記事では「DISTINCT」の使い方および、「GROUP BY」との違いについて説明していきます。
DISTINCTとは
「DISTINCT」とは、SQLで使用されるコマンドの一つで、SELECT文を実行した際の出力結果の重複レコード(データ行)を1つにまとめるための構文です。
例えば、商品名と個数の項目があるテーブルがあるとします。
商品名 | 数量 |
---|---|
テレビ | 10 |
テレビ | 10 |
洗濯機 | 7 |
同数同名の商品がある場合、「DISTINCT」を使うと次のようになります。
商品名 | 数量 |
---|---|
テレビ | 10 |
洗濯機 | 7 |
「DISTINCT」は重複した部分を1つにする機能を持っています。
GROUP BYとの違い
SQLで重複を削除する際に「GROUP BY」を使用する例も見られます。「DISTINCT」と「GROUP BY」は何が違うのでしょうか。
まず「GROUP BY」では、以下のような動きをしています。
1.指定された列名(属性)で行のグループ化を行う。
2.グループ化されたものから1行取り出す。
3.取り出された行を集約してテーブルを再構築する。
一方「DISTINCT」では、射影(テーブルの中から1部の列だけを取り出す)を行う段階で重複を排除します。
ただし、「GROUP BY」の場合は、重複排除した結果に対して何らかの処理を加えることができます。
つまり、
・「DISTINCT」は、重複削除を行った結果を出力したいときに使用
・「GROUP BY」は重複削除を行った結果に対して何らかの処理を加えたい場合に使用
という使用方法に関する違いが見られます。
DISTINCTの使い方
「DISTINCT」の構文は「SELECT」分と組み合わせるようにして使います。
SELECT DISTINCT 列名,列名・・・ FROM テーブル名
商品テーブルの「商品種別」を検索する例について、「DISTINCT」を使用した場合としない場合を見ていきます。
テーブルの作成:
1.CREATE TABLE distinct_sample(
2. No int NOT NULL, --商品コード
3. Puroduct varchar(255) NOT NULL, --商品
4. Type varchar(255) NOT NULL, --商品種別
5. PRIMARY KEY (No)
6.);
データの格納:
1.INSERT INTO distinct_sample VALUES('1001', '液晶', 'テレビ');
2.INSERT INTO distinct_sample VALUES('1002', '液晶', 'テレビ');
3.INSERT INTO distinct_sample VALUES('1003', 'プラズマ', 'テレビ');
DISTINCTを使わない場合:
1.mysql> SELECT Type from distinct_sample:
2.+-----------+
3.| Type |
4.+-----------+
5.| テレビ |
6.| テレビ |
7.| テレビ |
8.+-----------+
9.3 rows in set (0.00 sec)
DISTINCTを使う場合:
1.mysql> SELECT DISTINCT Type from distinct_sample:
2.+-----------+
3.| Type |
4.+-----------+
5.| テレビ |
6.+-----------+
7.1 rows in set (0.00 sec)
このように、「DISTINCT」を使用した場合、重複するレコードを1つにまとめて表示することが可能です。
次に「DISTINCT」を複数の列に対して使用する場合についてみていきます。
複数列におけるDISTINCTの使い方
「SELECT」文で複数列に対し検索結果を得る際に「DISTINCT」を使用すると、レコード単位に重複している行をまとめることができます。
商品テーブルの「商品」と「商品種別」を検索する例について、「DISTINCT」を使用した場合としない場合を見ていきます。
DISTINCTを使用しない場合:
1.mysql> SELECT Puroduct, Type from distinct_sample:
2.+-----------+---------+
3.| Puroduct | Type |
4.+-----------+---------+
5.| 液晶 | テレビ |
6.| 液晶 | テレビ |
7.| プラズマ | テレビ |
8.+-----------+---------+
9.3 rows in set (0.00 sec)
DISTINCTを使用した場合:
1.mysql> SELECT DISTINCT Puroduct, Type from distinct_sample:
2.+-----------+---------+
3.| Puroduct | Type |
4.+-----------+---------+
5.| 液晶 | テレビ |
6.| プラズマ | テレビ |
7.+-----------+---------+
8.2 rows in set (0.00 sec)
このように、「商品(Product)」と「商品種別(Type)」の2つの項目で重複しているレコードを1つのレコードにまとめて表示することができます。
次に「DISTINCT」で表示させた結果から件数を出力する方法についてみていきます。
出力結果の件数を調べる
出力結果の件数を調べるには、「DISTINCT」と「COUNT」を組み合わせて使用します。
SELECTする列が1件の場合と複数の場合について分けて解説します。
取得対象の列が1つの場合
取得対象の列が1つの場合はシンプルに下記のような構文になります。
SELECT COUNT(DISTINCT 列名) FROM テーブル名
レコード件数を数えてみます。
COUNTを使用する前:
1.mysql> SELECT DISTINCT Type from distinct_sample:
2.+-----------+
3.| Type |
4.+-----------+
5.| テレビ |
6.+-----------+
7.1 rows in set (0.00 sec)
COUNTを使用:
1.mysql> SELECT COUNT(DISTINCT Type) from distinct_sample;
2.+------------------------+
3.| COUNT(DISTINCT Type) |
4.+------------------------+
5.| 1 |
6.+------------------------+
7.1 row in set (0.00 sec)
このように「DISTINCT」の件数を数えることができます。
取得対象の列が複数ある場合
取得対象の列が複数ある場合は、列が1つになるように「CONCAT」で繋げたうえで重複を省きます。
SELECT COUNT( DISTINCT CONCAT(列名,列名...) FROM テーブル名
まず初めに、「COUNT」を使用せず、列を繋いだ結果を見てみます。
1.SELECT DISTINCT CONCAT(Puroduct, Type) result FROM distinct_sample;
2.+-----------------+
3.| result |
4.+-----------------+
5.| 液晶テレビ |
6.| プラズマテレビ |
7.+-----------------+
8.2 rows in set (0.00 sec)
次に「COUNT」を使用して出力してみます。
1.SELECT COUNT(DISTINCT CONCAT(Puroduct, Type)) result FROM distinct_sample;
2.+--------+
3.| result |
4.+--------+
5.| 2 |
6.+--------+
7.1 row in set (0.00 sec)
このように対象が複数あった場合でも、多少複雑にはなりますがレコード件数を出力することができます。
さいごに
いかがだったでしょうか。
本記事では、DISTINCTとGROUP BYはどちらも重複したレコードを1つにまとめる便利な構文ですが、処理の内容に違いがあるため使い分ける必要があります。
また、どちらの構文も頻繁に使われているものなので習得しておくと大変便利です。