【SQL】DISTINCTとは?重複行をまとめる基本の使い方から簡単な応用までわかりやすく解説!
多くの企業は、顧客情報や社員情報といった情報を管理するためにデータベースを活用しています。登録されているデータを分析して今後の見通しを立てるだけでなく、既存顧客へのマーケティングに活用できるため重要な情報です。
しかし、このデータに重複する内容があると正確な分析・顧客管理が行えません。そこで、重複行をまとめるのに有効なSQLコマンド「DISTINCT」が注目されています。本記事では、DISTINCTの概要を、使い方と併せて解説します。
SQLコマンド「DISTINCT」とは
DISTINCTはSQLのSELECT文とともに使用され、データベースから取得した結果の中で重複しているデータを取り除き、ユニークなデータだけを返すためのコマンドです。
SELECT文は、データベースから特定のデータを取得する際に使用する基本的なSQLの文法であり、DISTINCTを用いることで重複を簡単に除去することができます。
DISTINCTで何ができるのか
DISTINCTは、次のような場面で使用されます。
- テーブル内の列に多くの重複値が含まれる場合
- 特定の項目に絞り込んで、ユニークなリストを取得したい場合
- 対象のテーブルに同一の値を持つレコードがある中から、1つの値のみ選択したい場合
例えば、以下の社員表においてDISTINCTを使用すると重複する行が1つにまとめられます。
社員表:DISTINCT実行前
社員名 | 業務 | 部署 |
---|---|---|
山田 | 営業 | 東京 |
山田 | 営業 | 東京 |
荒井 | 人事 | 名古屋 |
社員表:DISTINCT実行後
社員名 | 業務 | 部署 |
---|---|---|
山田 | 営業 | 東京 |
荒井 | 人事 | 名古屋 |
重複していたデータが1つにまとまりました。上記の表のようにデータ量が少ない場合は、確認も容易でしょう。
しかし、数十件、数百件とデータが多くなるにつれ、人間の目でデータを確認するのは困難です。DISTINCTコマンドを利用すれば、データの重複をまとめ、必要な情報を容易に集められます。
GROUP BYとの違い
DISTINCTと似たコマンドに、GROUP BYがあります。重複レコードを1つにまとめて出力することはGROUP BYコマンドでも可能なため、GROUP BYを使用している方も多いでしょう。
DISTINCTとGROUP BYの違いは、実行する処理の内容です。
- DISTINCT
単純に重複する行を除外するために使用 - GROUP BY
特定の列でデータをグループ化し、そのグループに対して集計や演算を行うために使用
レコードから単純に重複を取り除きたい場合はDISTINCTが使えます。一方、レコードの内容をまとめて集計など何らかの処理を加えたい場合はGROUP BYが便利です。
例えば、以下の商品表においてGROUP BYを使って価格を集計した結果を見てみましょう。
商品表:GROUP BY実行前
商品 | 価格 |
---|---|
テレビ | 150,000 |
掃除機 | 14,000 |
テレビ | 198,000 |
テレビ | 98,000 |
掃除機 | 90,000 |
商品表:GROUP BY実行後(集計実施)
商品 | 価格 |
---|---|
テレビ | 446,000 |
掃除機 | 104,000 |
DISTINCTでは重複データを除外することしかできませんが、GROUP BYはテレビと掃除機をグループに分けて、それぞれの価格の合計値を算出することが可能です。合計だけでなく、平均値や最大・最小値の取得も行えます。種類ごとに合計値や平均値の値が欲しい場合は、GROUP BYを使いましょう。
また、DISTINCTとGROUP BYでは実行速度に差が出るケースがあります。大量のデータを扱う場合や、全件検索せざるを得ないクエリでは、ある程度の件数のテストデータを用いてレスポンスの違いを確認し、どちらを利用するか判断しましょう。
DISTINCTの使い方
SQLコマンドは、正しい文法で記述することで動作します。DISTINCTを使用した文法を覚えて、使い分けできるようにしましょう。
ここでは、DISTINCTの具体的な使い方を、SQL文の例や実行結果と合わせて解説します。
基本の使い方
DISTINCTは、SELECTの後に追加して、次のように記述します。
SELECT DISTINCT 列名,列名,…… FROM テーブル名;
DISTINCTの使用は、SELECTの直後に、1度だけ記述します。DISTINCTをSELECTの直後ではない場所に記述したり、2回以上記述したりするとエラーが発生するので注意が必要です
次に、実際にDISTINCTを使用するSQL文と、実行結果を確認しましょう。以下の社員表②から、どのような業務があるのか調べる場合の使用例です。
社員表②
社員ID | 社員名 | 部署 | 業務 | 性別 |
---|---|---|---|---|
01 | 山田 | 東京 | 営業 | 男 |
02 | 荒井 | 名古屋 | 人事 | 女 |
03 | 佐藤 | 仙台 | 経理 | 男 |
04 | 高橋 | 名古屋 | 営業 | 女 |
05 | 石田 | 名古屋 | 経理 | 男 |
06 | 田中 | 東京 | 営業 | 男 |
07 | 白崎 | 仙台 | 人事 | 女 |
SQL文は以下の通りです。
SELECT DISTINCT 業務 FROM 社員表;
実行結果は以下の通りです。
業務 |
営業 |
人事 |
経理 |
レコード単位に重複行をまとめる
DISTINCTコマンドは、複数の列に対して使用することが可能です。DISTINCTを複数の列に対して行うと、指定した列全てが一致したデータを除外して出力します。レコード単位で重複行をまとめる場合は、DISTINCTする列名をカンマで区切って記述しましょう。
上記の社員表②から、部署ごとに、どのような業務があるのか調べる場合の使用例です。SQL文は以下の通りです。
SELECT DISTINCT 部署,業務 FROM 社員表;
実行結果は以下の通りです。6つの項目が取得できます。
部署 | 業務 |
---|---|
東京 | 営業 |
東京 | 人事 |
仙台 | 経理 |
名古屋 | 営業 |
名古屋 | 経理 |
仙台 | 人事 |
なお、DISTINCTを使用すると、内部でソートしてから重複を削除する処理を行います。そのため、並び順が元のデータベースの順番と同じにならない場合があります。もし、並び順を揃えたい際は、「ORDER BY」を使用したSQL文に書き換えましょう。ORDER BYはソートを行うSQLコマンドです。
また、複数列を選択する場合に、片方の列にのみDISTINCTを適用することはできません。DISTINCTを使用する際は、重複を省きたい列だけを選択しましょう。
さらに、複数の列に対してDISTINCTを使用する際、文字列を連結してから重複を除外する方法もあります。文字列を連結するためには、CONCAT関数を使用します。文字列を連結しないとDISTINCTする列が複数の場合に検索したレコードを数えるSQL文が記述できません。
上記の社員表②から、部署と業務の文字列を連結して重複を除外する場合の使用例です。
SQL文は以下の通りです。
SELECT DISTINCT CONCAT(部署,業務) FROM 社員表;
実行結果は以下の通りです。
DISTINCT_CONCAT(部署,業務) |
東京営業 |
東京人事 |
仙台経理 |
名古屋営業 |
名古屋経理 |
仙台人事 |
COUNTと組み合わせる
DISTINCTで検索したレコードの件数を数える際は、COUNT関数を組み合わせましょう。DISTINCTする列の数に応じて、COUNTの直後に記述するSQL文が異なります。
DISTINCTで選択する列が1つの場合
COUNTを使用したSQL文は、次のように記述します。
SELECT COUNT(列名) FROM テーブル名;
DISTINCTで選択する列が1つの場合、()の中に「DISTINCT 列名」を記述しましょう。上記の社員表②から、業務は何種類あるのか出力する場合の使用例です。SQL文は以下の通りです。
SELECT COUNT(DISTINCT 業務) FROM 社員表;
実行結果は以下の通りです。
count |
3 |
DISTINCTで選択する列が複数の場合
COUNT関数に使用できる引数は、1つです。そのため、DISTINCTで選択する列が複数ある場合は、CONCATを用いて列を1つにした後、COUNTを処理します。
部署ごとの業務は、何種類あるのか出力する場合の使用例です。SQL文は以下の通りです。
SELECT COUNT(DISTINCT CONCAT(部署,業務) ) FROM 社員表;
実行結果は以下の通りです。
count |
6 |
カウントされている6種類は、「レコード単位に重複行をまとめる」の実行結果2で出力したデータです。COUNT関数で用いる()の中にCONCAT関数で用いる()が入るため、閉じ忘れに注意しましょう。
DISTINCTと他のSQLコマンドとの併用
DISTINCTと他のSQLコマンドとの併用 DISTINCTは他のSQLコマンドと組み合わせることで、より複雑なクエリを作成することができます。
特にJOINやHAVINGと組み合わせることで、複数のテーブルを対象としたユニークなデータ抽出や、条件に基づいた重複データの削除が可能です。
例えば、社員データと部署データを結合し、ユニークな社員の一覧を取得する場合のSQL文は以下の通りです。
SELECT DISTINCT 社員表.社員名, 部署表.部署名
FROM 社員表
JOIN 部署表 ON 社員表.部署ID = 部署表.部署ID;
このクエリは、社員表と部署表を結合し、ユニークな社員名と部署名を取得するものです。複数のテーブルから情報を抽出する際に、DISTINCTを活用することでデータの重複を防ぎ、正確な結果を得ることができます。
DISTINCTを使う際の注意点と代替手法
DISTINCTは、データベース内の重複データを効率的に除外する強力なSQLコマンドですが、注意点や代替手法を理解することが重要です。特に、NULLの扱いやパフォーマンス、複数列に対する適用方法には注意が必要です。
また、DISTINCTが提供できない機能(集計など)に対しては、GROUP BYやUNIQUE制約、などを使うことで、より柔軟なデータ処理が可能になります。それぞれの方法を適切に使い分けることで、効率的かつ正確なデータ管理が実現できるでしょう。
DISTINCTを使う際の注意点
DISTINCTを使う際の注意点 DISTINCTは便利なSQLコマンドですが、使用する際にはいくつかの注意点があります。
- NULLの扱い
DISTINCTを使用する場合、NULL値も1つとして扱われます。NULLが複数含まれる列でもDISTINCTはそれらを1つにまとめるため、意図した結果と異なる可能性があります。必要に応じて、WHERE句でNULLを除外してからDISTINCTを使用しましょう。 - パフォーマンス
大規模なデータセットに対してDISTINCTを使用すると、クエリの実行速度が低下することがあります。データ量が多い場合は、インデックスの最適化や不要な重複データを事前に削除するなどの対策を検討してください。
これらの点を理解しておくことで、DISTINCTの効率的な利用が可能になります。
DISTINCTの代替手法
UNIQUE制約との違い データベースでは、DISTINCT以外にも重複を防ぐ手法として「UNIQUE制約」があります。UNIQUE制約はテーブルの列に対して一意性を持たせるための制約で、重複するデータの挿入を事前に防ぐ役割を果たします。
一方、DISTINCTはデータを取得する際に重複行を取り除くためのSQLコマンドです。
- DISTINCT
取得時に重複行を除外 - UNIQUE制約
データの挿入時に重複を防止
例えば、顧客テーブルにUNIQUE制約を設定している場合、同じ顧客が複数回登録されることを防ぐことができますが、すでに重複しているデータに対してはDISTINCTを使用してユニークなデータを取得することが必要です。
このように、使用する目的やタイミングに応じてDISTINCTとUNIQUE制約を使い分けることでデータの一貫性を保つことができます。
まとめ
DISTINCTは、重複したレコードを除外し1つにまとめるSQLコマンドです。重複すると分析・管理に支障をきたすデータコントロールに役に立ちます。
ただし、DISTINCTは特定のデータをもとに集計する処理には向いていません。状況に応じて、GROUP BYと使い分け、情報を正確に分析し、分析結果を効果的に活用しましょう。