🧚 お知らせ!Beekeeper Studio は高速でモダンなオープンソースのデータベース GUI です ダウンロード
2025年7月21日 著者: Matthew Rathbone

COUNT(DISTINCT column) は、列に含まれる異なる値の数を数えます。10回出現する値も1つとして数え、NULL はまったく数えません。例は PostgreSQL、MySQL、SQLite、SQL Server で動作します。

COUNT DISTINCT の使い方

COUNT() の中で、数えたい列や式の前に DISTINCT を置きます。

COUNT(DISTINCT expression)

他の2つの COUNT の形式と並べると分かりやすいです。COUNT(*) は行数を、COUNT(column) は列が NULL でない行数を、COUNT(DISTINCT column) は NULL 以外の異なる値の数を数えます。

-- Input: orders
-- order_id | customer_id
-- ---------+------------
-- 1        | 1042
-- 2        | 1077
-- 3        | 1042
-- 4        | NULL

SELECT COUNT(*) AS all_rows,
       COUNT(customer_id) AS with_customer,
       COUNT(DISTINCT customer_id) AS customers
FROM orders;

-- Output:
-- all_rows | with_customer | customers
-- ---------+---------------+----------
-- 4        | 3             | 2

4件の注文は2人の顧客からのものです。1042 は2回注文しており、注文 4 には顧客がいません。

知っておくべきルール

  • NULL は数えられません。欠損値も1つとして数えたい場合は、自分で加算します。
-- Input: the orders table above

SELECT COUNT(DISTINCT customer_id)
       + MAX(CASE WHEN customer_id IS NULL THEN 1 ELSE 0 END) AS customers_and_guests
FROM orders;
-- Output: 3
  • MySQL と SQL Server はデフォルトで大文字・小文字を区別しないため、'SQL' と 'sql' を1つの値として数えます。大文字・小文字を区別したくない場合は LOWER(tag) を数えます。
-- Input: tags
-- post_id | tag
-- --------+---------
-- 1       | SQL
-- 2       | sql
-- 3       | Postgres

SELECT COUNT(DISTINCT tag) FROM tags;
-- Output: 3 (2 in MySQL and SQL Server)

SELECT COUNT(DISTINCT LOWER(tag)) FROM tags;
-- Output: 2
  • DISTINCT は SUM や AVG の中でも使えますが、取り除かれるのは重複した行ではなく重複した値です。同じ価格の異なる2つの商品は1回しか加算されません。
-- Input: order_lines
-- product  | price
-- ---------+------
-- Pen      | 2.00
-- Pencil   | 2.00
-- Notebook | 5.00

SELECT SUM(price) AS total, SUM(DISTINCT price) AS distinct_total FROM order_lines;

-- Output:
-- total | distinct_total
-- ------+---------------
-- 9.00  | 7.00

別の構文

COUNT(DISTINCT ...) は1つの列しか受け取りません。複数列の異なる組み合わせを数えるには、DISTINCT サブクエリの行数を数えます。PostgreSQL と MySQL には省略記法もあります。

-- Input: orders
-- order_id | customer_id | product_id
-- ---------+-------------+-----------
-- 1        | 1           | 23
-- 2        | 12          | 3
-- 3        | 1           | 23
-- 4        | 12          | 5

SELECT COUNT(*) FROM (SELECT DISTINCT customer_id, product_id FROM orders) AS pairs;
-- Output: 3

-- PostgreSQL
SELECT COUNT(DISTINCT (customer_id, product_id)) FROM orders;
-- Output: 3

-- MySQL
SELECT COUNT(DISTINCT customer_id, product_id) FROM orders;
-- Output: 3

CONCAT() で列を1つの文字列に連結する方法も見かけます。この場合は区切り文字が必要です。区切り文字がないと、顧客 1 と商品 23、顧客 12 と商品 3 がどちらも '123' になってしまいます。

-- Input: the orders table above

SELECT COUNT(DISTINCT CONCAT(customer_id, product_id)) FROM orders;
-- Output: 2

SELECT COUNT(DISTINCT CONCAT(customer_id, '_', product_id)) FROM orders;
-- Output: 3

正確な DISTINCT カウントはすべての値をソートまたはハッシュする必要があるため、非常に大きなテーブルでは遅くなります。SQL Server には APPROX_COUNT_DISTINCT() があり、より高速で、97% の確率で正確な値との誤差が 2% 以内に収まります。

-- SQL Server
-- Input: the orders table above

SELECT APPROX_COUNT_DISTINCT(customer_id) AS customers FROM orders;
-- Output: 2

COUNT DISTINCT はいつ使うべきか?

「何行あるか?」ではなく「異なる…はいくつあるか?」を知りたいときに COUNT DISTINCT を使います。そうした問いのほとんどは、次の4つのいずれかに当てはまります。

ユニークな訪問者・顧客・商品を数える

訪問・注文・売上のログには、同じ訪問者、顧客、商品が何度も記録されます。その ID に COUNT DISTINCT を使えば、行数を実際の人数や件数に変換できます。

グループごとにユニークな値を数える

GROUP BY を加えると、グループごとに DISTINCT カウントが得られます。コースごとの受講者数、ベンダーごとの商品数、月ごとの顧客数などです。

列のユニークな組み合わせを数える

2つの列が両方一致するときだけ2行が「同じ」とみなされる場合があります。同じユーザーの同じ種類の問題や、2つの空港間の同じ路線などです。「別の構文」で紹介した複数列の形式のいずれかで組み合わせを数えます。

条件を満たすユニークな値を数える

COUNT(DISTINCT ...) の中に CASE 式を入れると、一部の行だけを数えられます。CASE は不要な行に対して NULL を返し、NULL は数えられないため、1つのクエリで複数の絞り込みカウントを並べて返せます。

COUNT DISTINCT の実例

月間アクティブユーザー

9月に何らかの操作をしたユーザーを、何回戻ってきたかに関係なく数えます。

-- Input: events
-- event_id | user_id | event_date
-- ---------+---------+-----------
-- 1        | 301     | 2026-08-30
-- 2        | 302     | 2026-09-02
-- 3        | 302     | 2026-09-15
-- 4        | 305     | 2026-09-21
-- 5        | 302     | 2026-10-01

SELECT COUNT(DISTINCT user_id) AS active_users
FROM events
WHERE event_date >= '2026-09-01' AND event_date < '2026-10-01';
-- Output: 2

ベンダーごとの販売商品

COUNT(*) は各ベンダーの販売件数を、COUNT(DISTINCT product) はそれらの販売に含まれる異なる商品の数を返します。

-- Input: sales
-- vendor     | product  | color
-- -----------+----------+------
-- Acme       | Mug      | Red
-- Acme       | Mug      | Blue
-- Acme       | Mug      | Red
-- Acme       | Tote Bag | Red
-- Brightside | Notebook | Black

SELECT vendor, COUNT(*) AS sales, COUNT(DISTINCT product) AS products
FROM sales
GROUP BY vendor;

-- Output:
-- vendor     | sales | products
-- -----------+-------+---------
-- Acme       | 4     | 2
-- Brightside | 1     | 1

航空会社の運航路線

路線は出発地と目的地の組み合わせです。LHR から JFK への2便は1路線ですが、JFK から LHR は別の路線です。

-- Input: flights
-- flight_no | origin | destination
-- ----------+--------+------------
-- 101       | LHR    | JFK
-- 105       | LHR    | JFK
-- 102       | JFK    | LHR
-- 301       | LHR    | LAX

SELECT COUNT(*) AS routes
FROM (SELECT DISTINCT origin, destination FROM flights) AS r;
-- Output: 3

購入価格帯ごとの顧客

商品 100〜200 を購入した顧客を数え、注文の価格帯で分けます。顧客 7 は安価な注文を2回していますが1人として数え、顧客 15 の商品は範囲外です。

-- Input: orders
-- order_id | customer_id | product_id | price
-- ---------+-------------+------------+-------
-- 1        | 7           | 105        | 25.00
-- 2        | 7           | 142        | 40.00
-- 3        | 9           | 150        | 120.00
-- 4        | 12          | 188        | 310.00
-- 5        | 15          | 260        | 30.00

SELECT
  COUNT(DISTINCT customer_id) AS customers,
  COUNT(DISTINCT CASE WHEN price BETWEEN 1 AND 50 THEN customer_id END) AS low_spenders,
  COUNT(DISTINCT CASE WHEN price BETWEEN 51 AND 150 THEN customer_id END) AS mid_spenders,
  COUNT(DISTINCT CASE WHEN price > 150 THEN customer_id END) AS high_spenders
FROM orders
WHERE product_id BETWEEN 100 AND 200;

-- Output:
-- customers | low_spenders | mid_spenders | high_spenders
-- ----------+--------------+--------------+--------------
-- 3         | 1            | 1            | 1

2つの価格帯で注文した顧客は、両方で数えられます。

COUNT DISTINCT の関連資料

このブログの記事:

公式ドキュメント:

Beekeeper Studioは無料のオープンソースのデータベースGUIです

これまで使った中で最高のSQLクエリ&エディタツールです。データベースの管理に必要なものがすべて揃っています。 - ⭐⭐⭐⭐⭐ Mit

Beekeeper Studioは高速で直感的、そして使いやすいツールです。多数のデータベースに対応し、Windows、Mac、Linuxで快適に動作します。

BeekeeperのLinux版は100%フル機能。手抜きも機能の妥協も一切ありません。

Beekeeper Studio 利用者の声

★★★★★
「Beekeeper Studio は以前の SQL ワークフローを完全に置き換えました。高速で直感的、データベース作業がまた楽しくなりました。」
— Alex K.、データベース開発者
★★★★★
「多くのデータベース GUI を試しましたが、Beekeeper は機能とシンプルさのバランスが完璧です。とにかくちゃんと動きます。」
— Sarah M.、フルスタックエンジニア