COUNT

La función COUNT es probablemente la función de agregación que más usarás en MySQL. Sirve para contar filas en una tabla o en el resultado de una consulta. Parece simple, pero tiene matices importantes que conviene entender bien: la diferencia entre COUNT(*), COUNT(columna) y COUNT(expresion) determina qué filas se cuentan y cuáles se ignoran.

Sintaxis

COUNT(*)
COUNT(expresion)
COUNT(ALL expresion)

COUNT(*) cuenta todas las filas del grupo, incluyendo aquellas que contienen valores NULL. COUNT(expresion) cuenta solo las filas donde la expresión no es NULL. La palabra clave ALL es el comportamiento por defecto y raramente se escribe de forma explícita.

Cuando usas COUNT sin GROUP BY, MySQL trata toda la tabla como un único grupo y devuelve una sola fila con el resultado.

Comportamiento básico

COUNT(*) cuenta todas las filas

La forma más directa es contar el total de registros en una tabla:

SELECT COUNT(*) AS total_productos
FROM productos;
total_productos
50

COUNT(*) no examina el contenido de las columnas. Simplemente cuenta las filas que existen, sin importar si alguna columna contiene NULL. Internamente, MySQL optimiza COUNT(*) de forma especial: con el motor InnoDB utiliza el índice secundario más pequeño para hacer el conteo, lo que es más eficiente que escanear toda la tabla.

COUNT(columna) ignora los NULL

Supongamos que la tabla empleados tiene una columna telefono donde algunos empleados no han proporcionado su número:

SELECT
    COUNT(*) AS total_empleados,
    COUNT(telefono) AS con_telefono
FROM empleados;
total_empleadoscon_telefono
2519

Hay 25 empleados en total, pero solo 19 tienen un número de teléfono registrado. COUNT(telefono) descartó automáticamente las 6 filas donde telefono es NULL. Esta diferencia entre COUNT(*) y COUNT(columna) es fundamental y fuente de errores si no la tienes presente.

Caso práctico: conteo con GROUP BY

El verdadero poder de COUNT aparece cuando lo combinas con GROUP BY para obtener conteos por categoría. Veamos cuántos productos tiene cada categoría:

SELECT
    c.nombre AS categoria,
    COUNT(*) AS total_productos
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
ORDER BY total_productos DESC;
categoriatotal_productos
Smartphones12
Portátiles8
Accesorios electrónicos7
Ropa hombre6
Ropa mujer6
Hogar5
Deportes4
Libros2

Cada fila del resultado corresponde a un grupo distinto. MySQL agrupa las filas por c.nombre y luego aplica COUNT(*) dentro de cada grupo.

Caso práctico: conteo con WHERE

Puedes combinar COUNT con WHERE para contar solo las filas que cumplan una condición. Por ejemplo, contar los pedidos realizados en enero de 2026:

SELECT COUNT(*) AS pedidos_enero
FROM pedidos
WHERE fecha_pedido BETWEEN '2026-01-01' AND '2026-01-31';
pedidos_enero
134

También puedes combinar WHERE y GROUP BY para obtener conteos filtrados por grupo. Veamos cuántos pedidos completados tiene cada cliente:

SELECT
    cl.nombre,
    cl.apellidos,
    COUNT(*) AS pedidos_completados
FROM pedidos p
JOIN clientes cl ON p.cliente_id = cl.id
WHERE p.estado = 'completado'
GROUP BY cl.id, cl.nombre, cl.apellidos
ORDER BY pedidos_completados DESC
LIMIT 5;
nombreapellidospedidos_completados
MaríaGarcía López8
CarlosRodríguez Martín7
AnaMartínez Ruiz6
PedroSánchez Gómez5
LauraFernández Díaz5

El WHERE filtra las filas antes de que se formen los grupos, por lo que COUNT(*) solo cuenta los pedidos que ya pasaron el filtro.

Caso práctico: COUNT con expresiones

Puedes pasar una expresión a COUNT para contar filas que cumplen una condición sin necesidad de WHERE. Esto es útil cuando quieres varios conteos en la misma consulta:

SELECT
    COUNT(*) AS total_productos,
    COUNT(CASE WHEN precio > 1000 THEN 1 END) AS productos_premium,
    COUNT(CASE WHEN stock = 0 THEN 1 END) AS sin_stock
FROM productos;
total_productosproductos_premiumsin_stock
5083

La expresión CASE WHEN precio > 1000 THEN 1 END devuelve 1 cuando se cumple la condición y NULL cuando no se cumple (el ELSE NULL es implícito). Como COUNT ignora los NULL, solo cuenta las filas donde la condición es verdadera.

Manejo de NULL

Entender cómo COUNT maneja los NULL es crucial. Recapitulemos con un ejemplo claro:

SELECT
    COUNT(*) AS todas_las_filas,
    COUNT(descuento) AS con_descuento,
    COUNT(*) - COUNT(descuento) AS sin_descuento
FROM productos;
todas_las_filascon_descuentosin_descuento
501238

La resta entre COUNT(*) y COUNT(descuento) te da el número de productos donde descuento es NULL. Este patrón es una forma práctica de contar valores nulos sin usar una subconsulta.

Combinación con otras funciones

COUNT se combina frecuentemente con HAVING para filtrar grupos según su conteo:

SELECT
    c.nombre AS categoria,
    COUNT(*) AS total_productos
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
HAVING COUNT(*) >= 6
ORDER BY total_productos DESC;
categoriatotal_productos
Smartphones12
Portátiles8
Accesorios electrónicos7
Ropa hombre6
Ropa mujer6

HAVING se aplica después de la agrupación, a diferencia de WHERE que se aplica antes. Por eso puedes usar funciones de agregación en HAVING pero no en WHERE.

También puedes usar COUNT dentro de subconsultas para filtrar por conteo:

SELECT nombre, apellidos
FROM clientes
WHERE id IN (
    SELECT cliente_id
    FROM pedidos
    GROUP BY cliente_id
    HAVING COUNT(*) > 5
);

Esta consulta obtiene los clientes que tienen más de 5 pedidos.

Rendimiento de COUNT(*) con InnoDB

En versiones anteriores de MySQL con el motor MyISAM, COUNT(*) sin WHERE era instantáneo porque MyISAM almacenaba el conteo total de filas como metadato. Con InnoDB, que es el motor por defecto desde MySQL 5.5, esto ya no es así: InnoDB necesita recorrer un índice para contar las filas, porque el sistema de transacciones MVCC implica que distintas transacciones pueden ver distintas cantidades de filas. Si trabajas con tablas de millones de registros y necesitas un conteo aproximado frecuente, considera cachear el resultado o usar SHOW TABLE STATUS para obtener una estimación rápida.

Practica con COUNT

Usa el editor para contar filas con distintas condiciones:

Simulador SQL
Ctrl+Enter para ejecutar

En el siguiente artículo veremos COUNT DISTINCT para contar valores únicos.

Escrito por Eduardo Lázaro