構文解説2026/7/30

SQLのDISTINCT句:重複を排除してユニークな値を取得する方法

SQLを扱っていると、「重複したデータを除外して、ユニークな値だけを取得したい」という場面に頻繁に遭遇します。例えば、顧客リストから重複するメールアドレスを省いてユニークなリストを作成したい場合や、商品リストから重複するカテゴリ名を抽出したい場合などです。

このようなニーズに応えるのが、SQLのDISTINCT句です。

しかし、「DISTINCTって具体的にどう使うの?」「SELECT文のどこに書けばいいの?」といった疑問を持つ方もいるかもしれません。

この記事では、DISTINCT句の基本的な使い方から、少し応用的な使い方までを、具体的なSQLコード例を交えながら分かりやすく解説していきます。

DISTINCTを使いこなせるようになれば、より効率的かつ正確にデータを分析できるようになりますので、ぜひ最後までご覧ください。

SELECT文におけるDISTINCTの基本

DISTINCT句は、SELECT文で取得する結果セットから、指定した列の重複する値を取り除き、ユニークな値のみを返します。

最も基本的な使い方は、SELECTキーワードの直後にDISTINCTを記述することです。

例えば、usersテーブルからユニークなcity(都市名)のリストを取得したい場合、以下のようなSQL文になります。

SELECT DISTINCT city
FROM users;

このクエリは、usersテーブルに登録されているすべての都市名を検索し、その中から重複する都市名を削除して、ユニークな都市名のみを一覧表示します。

もしusersテーブルに以下のようなデータがあったとします。

idnamecity
1AliceTokyo
2BobOsaka
3CharlieTokyo
4DavidNagoya
5EveOsaka

上記のSELECT DISTINCT city FROM users;を実行すると、結果は以下のようになります。

city
Tokyo
Osaka
Nagoya

TokyoOsakaのように複数回出現する都市名も、DISTINCTによって1つにまとめられていることがわかります。

複数の列にDISTINCTを適用する場合

DISTINCT句は、単一の列だけでなく、複数の列に対して適用することも可能です。

複数の列にDISTINCTを適用した場合、指定したすべての列の組み合わせがユニークであるレコードのみが返されます。

例えば、ordersテーブルから、ユニークなcustomer_id(顧客ID)とorder_date(注文日)の組み合わせを取得したいとします。

SELECT DISTINCT customer_id, order_date
FROM orders;

この場合、customer_idorder_dateの両方が同じであるレコードは、重複とみなされ、一つだけが結果に含まれます。

customer_idが同じでもorder_dateが異なれば、それはユニークな組み合わせとして扱われます。

例えば、ordersテーブルに以下のようなデータがあったとします。

order_idcustomer_idorder_dateamount
10112023-10-265000
10222023-10-263000
10312023-10-277000
10412023-10-262000

この場合、SELECT DISTINCT customer_id, order_date FROM orders;を実行すると、結果は以下のようになります。

customer_idorder_date
12023-10-26
22023-10-26
12023-10-27

customer_idが1でorder_dateが2023-10-26のレコードは、order_idが異なっていても、customer_idorder_dateの組み合わせとしては重複しているとみなされます。そのため、order_idが101と104の2つのレコードのうち、どちらか一方が結果に含まれます(どのレコードが残るかはデータベースの実装によりますが、一般的にはいずれか一つです)。

customer_idが1でorder_dateが2023-10-27のレコードは、order_dateが異なるため、ユニークな組み合わせとして扱われます。

DISTINCTを複数の列に適用する際は、各列が独立してユニークになるのではなく、「列の組み合わせ」としてユニークになる点を理解しておくことが重要です。

GROUP BY句との違い

DISTINCT句と似たような目的で使われるものにGROUP BY句があります。

どちらも重複するデータをまとめる機能がありますが、その役割と使い方には明確な違いがあります。

GROUP BY句は、指定した列の値に基づいて行をグループ化し、各グループに対して集計関数(COUNT, SUM, AVG, MAX, MINなど)を適用するために使用されます。

一方、DISTINCT句は、単純に重複する行を削除し、ユニークな行のみを返します。集計関数と組み合わせて使うことも可能ですが、その場合はGROUP BY句を使った場合と結果が異なることがあります。

例えば、usersテーブルから各都市のユーザー数をカウントしたい場合を考えます。

GROUP BY句を使う場合:

SELECT city, COUNT(*) AS user_count
FROM users
GROUP BY city;

このクエリは、cityごとにグループ化し、各グループの行数をカウントします。結果は以下のようになります。

cityuser_count
Tokyo2
Osaka2
Nagoya1

DISTINCT句をCOUNT関数と組み合わせて使う場合:

SELECT COUNT(DISTINCT city) AS unique_city_count
FROM users;

このクエリは、usersテーブルに含まれるユニークなcityの数をカウントします。結果は以下のようになります。

| unique_city_count | |-------------------|--------| | 3 |

このように、COUNT(DISTINCT column_name)は、指定した列のユニークな値の数を数えるために使われます。

GROUP BYは「グループごとに集計したい」、COUNT(DISTINCT ...)は「ユニークな値の数を数えたい」という目的で使い分けることが重要です。

また、SELECT DISTINCT column1, column2 FROM table_name;は、GROUP BY column1, column2と結果が同じになる場合がありますが、これはGROUP BYの副次的な効果であり、DISTINCTの本来の目的は「重複行の削除」にあります。

パフォーマンスの観点からも、意図した結果を得るためには、それぞれの句の役割を正確に理解し、適切に使い分けることが推奨されます。

DISTINCTION句の応用と注意点

DISTINCT句は、データのクリーニングや集計の前処理として非常に役立ちます。しかし、いくつか注意すべき点もあります。

NULL値の扱い

DISTINCT句は、NULL値を他の値とは異なる特別な値として扱います。つまり、NULL値もユニークな値としてカウントされます。

例えば、productsテーブルに以下のようなデータがあったとします。

product_idcategory
1Books
2NULL
3Books
4NULL
5Clothing

SELECT DISTINCT category FROM products;を実行すると、結果は以下のようになります。

| category | |----------|----------| | Books | | NULL | | Clothing |

NULLが1つだけ結果に含まれていることがわかります。もしNULLを結果に含めたくない場合は、WHERE句で除外する必要があります。

SELECT DISTINCT category
FROM products
WHERE category IS NOT NULL;

このクエリでは、categoryNULLでないレコードのみを対象とするため、結果からNULLが除外されます。

パフォーマンスへの影響

DISTINCT句を使用すると、データベースは重複する値を見つけるために、結果セット全体をソートまたはハッシュ処理する必要があります。データ量が多い場合、この処理には時間がかかることがあります。

特に、複数の列にDISTINCTを適用した場合や、ORDER BY句と併用した場合、パフォーマンスに影響が出やすくなります。

もし、単にユニークな値の数を数えたいだけであれば、COUNT(DISTINCT column_name)を使用する方が、SELECT DISTINCT column_nameしてからCOUNT(*)するよりも効率的な場合が多いです。

パフォーマンスが問題になる場合は、インデックスの活用や、GROUP BY句での代替などを検討することも重要です。

LIMIT句との併用

DISTINCT句とLIMIT句を併用すると、ユニークな結果の中からさらに上位N件を取得することができます。

例えば、usersテーブルからユニークな都市名を5つ取得したい場合:

SELECT DISTINCT city
FROM users
LIMIT 5;

ただし、LIMIT句は結果セットの順序に依存するため、ORDER BY句を指定せずにLIMITを使用すると、どの5件が取得されるかは保証されません。

もし特定の順序で上位5件のユニークな都市名を取得したい場合は、ORDER BY句を併用する必要があります。

SELECT DISTINCT city
FROM users
ORDER BY city
LIMIT 5;

このクエリは、まず都市名をアルファベット順に並べ替え、その中から最初の5つのユニークな都市名を取得します。

DISTINCT句は、データの重複を取り除き、分析に必要なユニークな情報を効率的に抽出するための強力なツールです。その基本的な使い方から応用、注意点までを理解することで、SQLでのデータ操作の幅が大きく広がります。

今回学習したDISTINCT句は、データ分析の基本となる「重複排除」の操作です。この知識をさらに深めるために、ぜひ以下の練習問題に挑戦してみてください。

QSQL Quest