Posibilidades de la función COUNT de SQL

La de 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 permite 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 PosgreSQL, 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 agrupación:

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

Cuenta todas el número de veces que hay para cada valor distinto de price.

Teniendo en cuenta un campo

Veamos la siguiente variante:

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
Elementos distintos de un campo

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 algo 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'

Una de las ventajas de utilizar 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 el resultado para clasificar los diferentes valores, o evitar 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 de esos dos campos en cuyo caso sí obtendríamos las ventajas de utilizar un índice para esas dos cuentas.

Otras funciones de agregación

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

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 una estadística. Si además tenemos una correcta estrategia de índices aprovecharemos la eficiencia de la base de datos para realizar este trabajo.