Contenido de esta guía
Respuesta rápida
Si necesitas contar combinaciones únicas de varias columnas, el patrón más claro y portable es crear primero las filas distintas y contarlas después:
SELECT COUNT(*) AS combinaciones_distintas
FROM (
SELECT DISTINCT columna_a, columna_b
FROM tabla
) AS combinaciones;La subconsulta responde primero “¿qué combinaciones diferentes existen?”. El COUNT(*) exterior responde después “¿cuántas combinaciones son?”. Este orden evita depender de una sintaxis específica del motor y hace visible la unidad que estás contando.
No cuentas columnas: cuentas pares o tuplas
COUNT(DISTINCT ciudad) cuenta ciudades diferentes. Si añades otra columna, la pregunta cambia: ya no buscas ciudades únicas, sino combinaciones únicas como (Madrid, activo) y (Madrid, inactivo).
Modelo mental: trata las columnas elegidas como una clave compuesta temporal. Dos filas pertenecen a la misma combinación solo cuando coinciden en todas esas columnas.
Ejemplo comprobado: ciudad y estado del cliente
En la base educativa hay 12 clientes, 6 ciudades distintas y 7 combinaciones distintas de ciudad y activo. Madrid aparece con clientes activos e inactivos, por eso añade dos combinaciones aunque siga siendo una sola ciudad.
SELECT COUNT(*) AS combinaciones_distintas
FROM (
SELECT DISTINCT ciudad, activo
FROM clientes
) AS combinaciones;| combinaciones_distintas |
|---|
| 7 |
Para ver qué está contando realmente la consulta, ejecuta solo la parte interior:
SELECT DISTINCT ciudad, activo
FROM clientes
ORDER BY ciudad, activo;| ciudad | activo |
|---|---|
| A Coruña | 1 |
| Bilbao | 1 |
| Madrid | 0 |
| Madrid | 1 |
| Sevilla | 1 |
| Valencia | 1 |
| Zaragoza | 1 |
Sintaxis según el motor
El patrón con SELECT DISTINCT dentro de una subconsulta es una opción fácil de leer y funciona con PostgreSQL, MySQL, SQL Server y SQLite. Algunos motores ofrecen además una forma abreviada, pero no usan la misma sintaxis.
PostgreSQL
PostgreSQL permite construir un valor de fila y pasarlo como una sola expresión al agregado:
SELECT COUNT(DISTINCT (ciudad, activo))
FROM clientes;MySQL
MySQL admite varias expresiones directamente dentro de COUNT(DISTINCT ...):
SELECT COUNT(DISTINCT ciudad, activo)
FROM clientes;SQL Server y SQLite
La sintaxis documentada de COUNT(DISTINCT expresión) recibe una sola expresión. Para contar combinaciones sin inventar una codificación propia, usa la subconsulta con SELECT DISTINCT y luego COUNT(*).
Qué cambia cuando hay NULL
Los atajos por motor no deben tratarse como intercambiables cuando alguna columna puede contener NULL. La documentación de MySQL indica que su forma con varias expresiones cuenta combinaciones que no contienen NULL. Si necesitas conservar combinaciones donde una de las columnas sea nula, el patrón con SELECT DISTINCT hace explícitas esas filas antes del recuento y resulta más fácil de verificar.
En este ejemplo ciudad y activo son columnas no nulas, así que las tres formas mostradas producen el mismo total de 7 en los motores donde su sintaxis correspondiente está disponible.
Errores frecuentes
Contar cada columna por separado
COUNT(DISTINCT ciudad) y COUNT(DISTINCT activo) responden dos preguntas independientes. Sumar o multiplicar esos resultados no te da necesariamente el número de combinaciones presentes.
Concatenar columnas sin un separador seguro
COUNT(DISTINCT columna_a || columna_b)Valores diferentes pueden producir la misma cadena: ('ab','c') y ('a','bc') se convierten ambos en 'abc'. Además, el operador o función de concatenación varía entre motores.
Olvidar cuál es la unidad de análisis
Si la pregunta es “¿cuántas ciudades hay?”, usa una columna. Si es “¿cuántos estados de cliente existen por ciudad?”, necesitas la combinación. El SQL correcto depende primero de la pregunta.
Práctica guiada
Usa la tabla pedidos y devuelve cuántas combinaciones distintas de cliente_id y estado existen.
Resultado esperado: 14 combinaciones.
Criterio de éxito: la consulta debe contar combinaciones, no filas de pedido ni clientes por separado.
Pista 1
Empieza mostrando solo cliente_id y estado con SELECT DISTINCT.
Pista 2
Convierte ese resultado en una subconsulta con alias y aplica COUNT(*) por fuera.
Ver solución
SELECT COUNT(*) AS combinaciones
FROM (
SELECT DISTINCT cliente_id, estado
FROM pedidos
) AS combinaciones;Primero se reduce la tabla a una fila por combinación de cliente y estado. Después se cuentan esas filas ya deduplicadas.
Qué debes recordar
COUNT(DISTINCT columna)cuenta valores distintos de una sola expresión.- Para varias columnas, piensa en combinaciones o tuplas, no en conteos independientes.
- La subconsulta
SELECT DISTINCT ...+COUNT(*)es un patrón claro y portable. - PostgreSQL y MySQL ofrecen atajos distintos; SQL Server y SQLite se expresan de forma más directa con la subconsulta.
- Revisa el comportamiento de
NULLantes de sustituir el patrón portable por un atajo del motor.