MEDIA

メディア

  1. TOP
  2. メディア
  3. プログラミング
  4. SQLのDISTINCT完全解説|重複排除・COUNT・GROUP BYとの違いと最適化

SQLのDISTINCT完全解説|重複排除・COUNT・GROUP BYとの違いと最適化

「SQLで一覧を取得したら同じ値が何度も出てくる…」
「JOINしたら行数が想定より増えた…」
「ユニークな件数を正しく数えたい…」

こうした悩みを解決するのが DISTINCT です。

しかし実務では、

  • DISTINCTを付けたのに結果が減らない
  • COUNT(DISTINCT)で想定と違う件数になる
  • パフォーマンスが急に悪化する
  • JOINの重複を“隠しているだけ”になっている

といった問題も頻発します。

この記事では、

  • DISTINCTの正しい仕組み
  • 複数列での挙動
  • COUNT(DISTINCT)の注意点
  • GROUP BY・EXISTSとの違い
  • パフォーマンス最適化
  • 実務での設計判断

まで、現場視点で徹底解説します。

初心者にも分かりやすく、かつ実務経験者が納得できる深さで整理します。

DISTINCTの基礎知識

DISTINCTとは何か?

DISTINCTは、SELECT結果から重複行を除外する構文です。

重要なのは次の2点です。

  • テーブルのデータは変更しない
  • SELECTで指定した列の値で重複判定が行われる

つまり、表示結果だけを整えるための指定です。

基本構文

SELECT DISTINCT 列名 FROM テーブル名;

ポイント:

  • DISTINCTはSELECTの直後に1回だけ書く
  • 列ごとではなくSELECT全体にかかる
  • 重複判定は「SELECTした列の組み合わせ」

サンプルで理解するDISTINCTの動き

DISTINCTなし

SELECT last_name FROM players;

データが4行あり、姓がすべて「Sato」なら:

Sato Sato Sato Sato

DISTINCTあり

SELECT DISTINCT last_name FROM players;

結果:

Sato

行数が4→1に減ります。

DISTINCTは「値を変える」のではなく、同じ行をまとめる動作をします。

複数列でDISTINCTを使う

SELECT DISTINCT col1, col2 FROM テーブル名;

重複判定は「col1だけ」ではありません。

col1とcol2の組み合わせ単位です。

よくある誤解:

col1だけユニークにしたい

これはできません。
その場合は、必要な列だけをSELECTします。

COUNT(DISTINCT ...) の正しい使い方

1列のユニーク件数

SELECT COUNT(DISTINCT last_name) FROM players;

NULLの扱い

  • COUNT(DISTINCT)はNULLを数えない
  • NULLを1種類として扱うなら

複数列のCOUNT(DISTINCT)

DBによって方言があります。

MySQLでは可能:

COUNT(DISTINCT col1, col2)

PostgreSQLでは以下形式:

COUNT(DISTINCT (col1, col2))

公式ドキュメント参照:

移植性を重視するなら:

SELECT COUNT(*) FROM ( SELECT col1, col2 FROM table GROUP BY col1, col2 ) sub;

DISTINCTとGROUP BYの違い

目的 DISTINCT GROUP BY
重複排除
集計 ×
拡張性

DISTINCTが向いている場面

  • 選択肢リスト作成
  • ユニーク一覧取得
  • JOIN後の軽い整理

GROUP BYが向いている場面

  • 部署ごとの人数
  • 売上集計
  • グループ単位の条件判断

実務で最も多いDISTINCTの誤用

① JOINの重複を隠しているだけ

SELECT DISTINCT customers.* FROM customers JOIN orders ...

本当に必要なのは:

SELECT * FROM customers c WHERE EXISTS ( SELECT 1 FROM orders o WHERE o.customer_id = c.id );

存在確認ならEXISTSが正解です。

② SELECT列が多すぎる

余計な列を含めると重複が消えません。

  •  必要最小限の列に絞る
  •  何をユニークにしたいか明確にする

NULLの扱いの本質

DISTINCTではNULLも「1種類」として扱われます。

例:

NULL NULL NULL

NULL

NULLを除外するなら:

WHERE col IS NOT NULL

パフォーマンスへの影響

DISTINCTは内部的に:

  • ソート
  • ハッシュ集計

を行います。

以下の場合は遅くなりやすい:

  • 大量データ
  • 文字列が長い
  • 対象列が多い
  • WHEREで絞り込みが弱い

パフォーマンス改善の基本

  1. WHEREで先に絞る

  2. SELECT列を減らす

  3. インデックスを適切に張る

  4. 重複が出ない設計にする

公式リファレンス:

DISTINCTの代替手法

GROUP BY

SELECT col FROM table GROUP BY col;

将来的に集計追加するならこちら。

EXISTS

JOIN+DISTINCTよりも明確。

ウィンドウ関数(高度)

PostgreSQLやMySQL8以降なら:

ROW_NUMBER() OVER (PARTITION BY col ORDER BY id)

重複の原因分析に有効。

実務設計で考えるべきこと

DISTINCTは「便利な後処理」です。

しかし本質的には:

  • なぜ重複が発生しているか?
  • データ設計は適切か?
  • ユニーク制約は張るべきか?

ここまで考えるのが、エンジニアの仕事です。

まとめ

DISTINCTは:

  • SELECT結果から重複を除外する構文
  • 判定はSELECT列の組み合わせ単位
  • COUNT(DISTINCT)で種類数取得可能
  • GROUP BYやEXISTSと使い分ける
  • パフォーマンスと設計意図に注意する

正しく使えば、SQLは読みやすく、正確で、高速になります。

次のステップ

もしこの記事を読んで、

  • SQLの最適化をもっと極めたい
  • データ設計から関わりたい
  • パフォーマンス改善に挑戦したい
  • 本質的なDB設計力を身につけたい

と感じたなら、あなたは既に“次の段階”にいます。

私たちは、
データ設計・DB最適化・アプリケーション設計まで一貫して考えるエンジニアチームです。

単なるCRUD開発ではなく、

  • なぜそのクエリなのか
  • なぜその設計なのか
  • なぜその制約なのか

を議論しながら成長できる環境があります。

SQLやデータ設計に強いエンジニアとして本気で成長したい方は、ぜひ私たちの採用情報もご覧ください。

技術を深く理解したいあなたと、一緒に働ける日を楽しみにしています。

学んだSQLを、実務で使えるスキルにしたい方へ

本記事ではSQLの基本的な考え方や使い方を解説しましたが、
「実務で使えるレベルまで身につけたい」と感じた方も多いのではないでしょうか。

SQLは、文法を理解するだけでなく、

  • どんなデータ構造で使われるのか
  • どんなクエリが現場で求められるのか

を意識して学ぶことで、実践力が大きく変わります。

そうした「実務を見据えたSQL学習」を進めたい方には、
完全無料で学べるプログラミングスクール ZeroCode という選択肢もあります。

  • SQLを含むWeb・データベース系スキルを体系的に学べる
  • 未経験者でも実務を意識したカリキュラム
  • 受講料・教材費がかからない完全無料の学習環境
  • 完全オンラインでスキマ学習


ZeroCodeについて詳しく見る

※学習内容や進め方を確認するだけでもOKです

Join us! 未経験からエンジニアに挑戦できる環境で自分の可能性を信じてみよう 採用ページを見る→

記事監修

ドライブライン編集部

[ この記事をシェアする ]

記事一覧へ戻る