Posibilidades de la función COUNT de SQL

Cosas que se pueden hacer con la función SQL COUNT()

El uso más típico de la función de agregación COUNT es count(*) donde ponemos en las condiciones del WHERE qué es lo que queremos contar y listo. Pero la sintaxis de COUNT y SQL permiten hacer muchas más cosas y además suele ser más eficiente que traer todos los datos y hacerlo desde nuestro propio código.

La sintaxis de los ejemplos mostrados aquí es para MySQL pero es similar con PostgreSQL, Oracle, MSQL, etc.

Contar todas filas de una query

Esta es la más común, contar las filas devueltas por una sentencia SQL:

SELECT COUNT(*) FROM products WHERE active=1
Agrupando por una o varias columnas

También bastante común agrupar por columnas y devolver la cuenta de cada una:

SELECT price, COUNT(*) FROM products GROUP BY price

Agrupa cada uno de los valores distintos de price y nos muestra cuantos hay de cada valor.

Teniendo en cuenta una columna

Veamos la siguiente variante donde cambiamos el * (que se refiere a todas las filas) por un campo concreto:

SELECT COUNT(price) FROM products

En este caso lo que hará es devolvernos la cuenta de todas las filas cuyo campo price no sea null (el 0 no es nulo). Similar a:

SELECT COUNT(*) FROM products WHERE price IS NOT NULL
Cuantos elementos distintos hay en una columna

Obtención del número de valores diferentes de una columna.

SELECT COUNT(DISTINCT price) FROM products

Agrupa todos los elementos price distintos y que no sean nulos, contamos así el número de elementos diferentes de la columna. También es posible añadir una expresión en lugar de un campo como veremos a continuación.

Contar con expresiones

La función COUNT permite no solo campos sino también añadir expresiones con IF, IFNULL y CASE. Vamos con un ejemplo:

SELECT COUNT(IF(declared = 'new', 1, NULL)) FROM products

Como sabemos, COUNT cuenta elementos no nulos, lo que hacemos con la expresión es anular lo que no cumple nuestra condición y contará solo resultados cuya condición devuelve un valor no nulo. De forma análoga se puede reescribir como:

SELECT COUNT(CASE WHEN declared = 'new' THEN 1 ELSE NULL END) FROM products

SELECT COUNT(*) FROM products WHERE declared='new'

Pero una de las ventajas de utilizar expresiones en COUNT (u otras funciones de agregación que permiten expresiones) es poder calcular diferentes resultados en una misma query, y si tiene un índice asociado aprovecharnos de las ventajas que esto conlleva. Por ejemplo:

SELECT
    COUNT(IF(declared = 'new', 1, NULL)) nuevos,
    COUNT(IF(declared = 'used', 1, NULL)) usados,
    COUNT(IF(declared = 'broken', 1, NULL)) rotos
FROM products

Suponiendo que tenemos un índice sobre el campo declared aprovecharemos una respuesta más eficiente de la base de datos en lugar de obtener millones de productos y recorrer nosotros mismos los resultados para clasificar los diferentes valores; o evitando lanzar 3 queries diferentes. Si no existe índice asociado la base de datos tendrá que leer toda la tabla para calcular el resultado.

Otro ejemplo:

SELECT
    COUNT(IF(declared = 'new', 1, NULL)) nuevos,
    COUNT(IF(active = 1, 1, NULL)) activos
FROM products

Aquí estamos utilizando dos campos diferentes, y en el caso de MySQL que solo utiliza un índice, tendría que hacer un fullscan de la tabla para obtener los resultados, salvo que tengamos un índice compuesto sobre esos dos campos en cuyo caso sí obtendríamos las ventajas de utilizar un índice para esos dos COUNT.

Otras funciones de agregación y más expresiones

En SQL tenemos otras funciones de agregación como son AVG, MAX, MIN, SUM, STD, etc. que también pueden hacer uso de las expresiones que hemos visto para COUNT. Un ejemplo:

SELECT
    COUNT(IF(price > 0 AND active = 1, 1, NULL)) en_venta,
    COUNT(IF(price = 0 OR active = 0, 1, NULL)) nulos,
    MAX(IF(active = 1, price, 0)) precio_max,
    AVG(IF(price > 0 AND active = 1, price, NULL)) precio_medio,
    SUM(IF(price > 0 AND active = 1, price, 0)) suma_total
FROM products

NOTA: Para AVG los valores nulos no se tienen en cuenta para la media, en el ejemplo anterior se utiliza NULL para ello y la expresión descarta así precios 0 o negativos. Si utilizáramos un 0 en lugar de NULL (como el caso de SUM), esos 0 se tendrían en cuenta en el cálculo de la media.

Conclusión

Suele ser útil delegar a la base de datos muchos de los cálculos, evitamos el tráfico de datos entre la base de datos y la aplicación si realmente solo queremos obtener una estadística. Si además tenemos una correcta estrategia de índices aprovecharemos la eficiencia de la base de datos para realizar este trabajo.