COUNT(DISTINCT column) cuenta cuántos valores distintos tiene una columna: un valor que aparece diez veces cuenta una sola vez, y los NULL no cuentan para nada. Los ejemplos funcionan en PostgreSQL, MySQL, SQLite y SQL Server.
Cómo usar COUNT DISTINCT
Pon DISTINCT dentro de COUNT(), antes de la columna o expresión que quieres contar:
COUNT(DISTINCT expression)
Se entiende mejor junto a las otras dos formas de COUNT. COUNT(*) cuenta filas, COUNT(column) cuenta las filas donde la columna no es NULL, y COUNT(DISTINCT column) cuenta los distintos valores que no son 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
Cuatro pedidos vinieron de dos clientes: 1042 pidió dos veces, y el pedido 4 no tiene cliente.
Reglas que debes conocer
- Los NULL no se cuentan. Si un valor faltante debe contar como uno más, súmalo tú:
-- 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 y SQL Server ignoran mayúsculas y minúsculas por defecto, así que cuentan
'SQL'y'sql'como un solo valor. CuentaLOWER(tag)cuando no deban importar las mayúsculas:
-- 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 también funciona dentro de
SUMyAVG, pero descarta valores repetidos, no filas repetidas. Dos productos distintos con el mismo precio se suman solo una vez:
-- 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
Sintaxis alternativa
COUNT(DISTINCT ...) acepta una sola columna. Para contar las distintas combinaciones de varias columnas, cuenta las filas de una subconsulta con DISTINCT. PostgreSQL y MySQL también tienen atajos:
-- 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
También vas a ver las columnas unidas en una sola cadena con CONCAT(). Necesita un separador: sin él, el cliente 1 con el producto 23 y el cliente 12 con el producto 3 se convierten ambos en '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
Un conteo exacto de distintos tiene que ordenar o aplicar hash a cada valor, lo cual se vuelve lento en tablas muy grandes. SQL Server tiene APPROX_COUNT_DISTINCT(), que es más rápido y se mantiene dentro del 2% del conteo exacto el 97% de las veces:
-- SQL Server
-- Input: the orders table above
SELECT APPROX_COUNT_DISTINCT(customer_id) AS customers FROM orders;
-- Output: 2
¿Cuándo deberías usar COUNT DISTINCT?
Usa COUNT DISTINCT cuando la pregunta es “¿cuántos … distintos?” y no “¿cuántas filas?”. La mayoría de esas preguntas caen en uno de estos cuatro casos.
Contar visitantes, clientes o productos únicos
Un registro de visitas, pedidos o ventas guarda al mismo visitante, cliente o producto una y otra vez. COUNT DISTINCT sobre su ID convierte esas filas en un conteo de cabezas.
Contar valores únicos en cada grupo
Agrega GROUP BY y obtienes un conteo de distintos por grupo: estudiantes distintos por curso, productos distintos por vendedor, clientes distintos por mes.
Contar combinaciones únicas de columnas
A veces dos filas solo son “iguales” cuando coinciden dos columnas: el mismo usuario con el mismo tipo de problema, o la misma ruta entre dos aeropuertos. Cuenta las combinaciones con alguna de las formas de varias columnas de “Sintaxis alternativa”.
Contar valores únicos que cumplen una condición
Pon una expresión CASE dentro de COUNT(DISTINCT ...) para contar solo algunas filas. El CASE devuelve NULL para las filas que no quieres, y los NULL no se cuentan, así que una sola consulta puede devolver varios conteos filtrados lado a lado.
Ejemplos reales de COUNT DISTINCT
Usuarios activos mensuales
Cuenta los usuarios que hicieron algo en septiembre, sin importar cuántas veces regresaron:
-- 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
Productos vendidos por cada vendedor
COUNT(*) da el número de ventas de cada vendedor, y COUNT(DISTINCT product) cuántos productos distintos abarcaron esas ventas:
-- 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
Rutas que vuela una aerolínea
Una ruta es un origen y un destino juntos. Dos vuelos de LHR a JFK son una sola ruta, pero de JFK a LHR es otra:
-- 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
Clientes según el precio de lo que compraron
Cuenta los clientes que compraron los productos 100 a 200 y luego sepáralos según el precio de sus pedidos. El cliente 7 hizo dos pedidos baratos pero cuenta una vez, y el producto del cliente 15 está fuera del rango:
-- 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
Un cliente con pedidos en dos rangos de precio se cuenta en ambos.
Más lecturas sobre COUNT DISTINCT
En este blog:
-
Guía de SQL GROUP BY:
COUNT,SUMyAVGpara cada grupo - Guía para encontrar duplicados en SQL: encuentra los valores que aparecen más de una vez
- Guía para eliminar duplicados en SQL: borra las copias sobrantes
- Guía de la sentencia CASE en SQL: las condiciones detrás de los conteos condicionales
-
Having vs Where en SQL: filtra por un conteo con
HAVING - Hoja de referencia de SQL: agregaciones y el resto de SQL en una página
Documentación oficial:
- PostgreSQL: expresiones de agregación
- MySQL: COUNT(DISTINCT)
- SQLite: count()
- SQL Server: COUNT y APPROX_COUNT_DISTINCT
Beekeeper Studio es un cliente de bases de datos gratuito y de código abierto
La mejor herramienta de consultas y edición de SQL que he usado. Tiene todo lo que necesito para administrar mi base de datos. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio es rápido, intuitivo y fácil de usar. Es compatible con muchísimas bases de datos y funciona de maravilla en Windows, Mac y Linux.
Lo que dicen los usuarios de Beekeeper Studio
"Beekeeper Studio reemplazó por completo mi antiguo flujo de trabajo con SQL. Es rápido, intuitivo y hace que trabajar con bases de datos vuelva a ser agradable."
"He probado muchas GUI de bases de datos, pero Beekeeper logra el equilibrio perfecto entre funciones y simplicidad. Simplemente funciona."