一意性におけるDISTINCTとGROUP BYの違い
DISTINCTを使うべき場合と、面接官がGROUP BYを期待する場合を学びます。
「一意性におけるDISTINCTとGROUP BYの違い」はCoddyKit上の無料SQL Interview Prepレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Interview Prepコースには全4レッスンが含まれています。
DISTINCTの動作
DISTINCTは重複する行を削除します。面接で確認される重要な点は、1つの列ではなく、選択した行全体に対して作用することです。つまり、SELECT DISTINCT a, bでは(a, b)の組み合わせが重複排除されます。
SELECT DISTINCT department
FROM employees;DISTINCTは選択したすべての列に適用される
複数の列を指定すると、DISTINCTは一意な組み合わせをそれぞれ残します。つまり、(department, job_title)の組み合わせごとに1行になります。1つの列だけを重複排除する標準的な方法はありません。
SELECT DISTINCT department, job_title
FROM employees;GROUP BYの動作
GROUP BYは、同じキーを持つ行を1つのグループにまとめ、グループごとに1行にします。単独で1列をGROUP BYすると、その列に対するDISTINCTと同じ結果になります。
SELECT department
FROM employees
GROUP BY department;
-- equivalent to:
SELECT DISTINCT department
FROM employees;本当の違い:集約
では、両者が異なるのはどんなときでしょうか。集約が必要なときです。GROUP BYではグループごとにCOUNT、SUM、AVGを計算できますが、DISTINCTではできません。一意な行が必要ならDISTINCT、グループごとの指標が必要ならGROUP BYを使います。
SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department;DISTINCTではグループごとの集計はできない
DISTINCTに集計を追加することはできません。「部署ごとの従業員数」のような処理には、SELECT DISTINCTではなく、COUNT(*)とGROUP BYを使うのが正しい方法です。
-- WRONG intent: this errors or returns one total row
-- SELECT DISTINCT department, COUNT(*) FROM employees;
-- RIGHT:
SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department;COUNT(DISTINCT)で両方の考え方を組み合わせる
よく使われる組み合わせがCOUNT(DISTINCT col)です。各グループ内の一意な値を数えられます。ここではDISTINCTを集約関数の中に置き、「部署ごとに異なる役職名はいくつあるか」という問いに答えています。
SELECT department,
COUNT(DISTINCT job_title) AS distinct_titles
FROM employees
GROUP BY department;全体で一意な値を数える
GROUP BYを使わない場合、COUNT(DISTINCT col)はテーブル全体の一意な値を数えます。「異なる部署はいくつあるか」という問いに対する、簡潔な答えです。
SELECT COUNT(DISTINCT department) AS n_departments
FROM employees;
-- equivalently, count the deduped subquery
SELECT COUNT(*)
FROM (SELECT DISTINCT department FROM employees) d;パフォーマンスに大差がないことが多い
DISTINCTとGROUP BYではどちらが速いのでしょうか。単純な重複排除であれば、通常は同等です。オプティマイザが同じような実行計画を作るためです。意図に応じて、一意な行にはDISTINCT、集約にはGROUP BYを選びます。
DISTINCTとNULL
DISTINCTはNULLをどのように扱うのでしょうか。すべてのNULLを等しいものとして扱うため、多数のNULL行は1行にまとめられます。GROUP BYも同じで、NULLは1つのグループを形成します。
-- If manager_id has several NULLs, this returns one NULL row
SELECT DISTINCT manager_id
FROM employees;PostgresのDISTINCT ON(応用)
応用として、Postgresには標準外のDISTINCT ON (expr)があります。ORDER BYで指定した順序に基づき、キーごとに先頭の行を残します。移植性のあるコードでは、代わりにROW_NUMBER()を使います。
-- Postgres only: latest order per customer
SELECT DISTINCT ON (customer_id) customer_id, order_id, order_date
FROM orders
ORDER BY customer_id, order_date DESC;DISTINCTは1つの列ではなくSELECT全体に適用される
もう1つの落とし穴です。DISTINCTは行全体に作用するため、SELECT DISTINCT customer_id, order_dateでは顧客ごとに1行にはなりません。その場合は、MAXを使うGROUP BYまたはウィンドウ関数を使用します。
-- Does NOT give one row per customer
SELECT DISTINCT customer_id, order_date FROM orders;
-- One row per customer: latest order date
SELECT customer_id, MAX(order_date) AS last_order
FROM orders
GROUP BY customer_id;確認問題
適切なツールを選びましょう。
まとめ
まとめると、DISTINCTは行全体の重複を排除し、GROUP BYはキーごとに行をまとめて集約を可能にします。COUNT(DISTINCT col)は一意な値を数え、どちらもNULLを1つとして扱います。パフォーマンスには通常大差ありません。
よくある質問
「一意性におけるDISTINCTとGROUP BYの違い」レッスンは無料ですか?
はい。「一意性におけるDISTINCTとGROUP BYの違い」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Interview Prepコースには全4レッスンが含まれています。
「一意性におけるDISTINCTとGROUP BYの違い」で何を学びますか?
DISTINCTを使うべき場合と、面接官がGROUP BYを期待する場合を学びます。 ブラウザで直接実行するハンズオンコードでSQL Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Interview Prepを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「一意性におけるDISTINCTとGROUP BYの違い」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Interview Prepレッスンでコードを書いて実行できますか?
はい。すべてのSQL Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 列の射影とエイリアスの落とし穴
- 計算列と式の優先順位
- 一意性におけるDISTINCTとGROUP BYの違い
- SELECT内のCASE式