Menu
Probar en el Playground

Funciones de agregación en SQLite: COUNT, SUM, AVG

Cómo las funciones de agregación de SQLite reducen muchas filas a un único valor: COUNT, SUM, AVG, MIN, MAX y GROUP_CONCAT, con DISTINCT, FILTER y el manejo de NULL.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Qué hace realmente una función de agregación

La mayoría de las funciones SQL que has visto hasta ahora trabajan fila por fila: UPPER(name) se ejecuta una vez por cada fila, igual que ROUND(price, 2). Las funciones de agregación SQLite funcionan distinto: toman un conjunto entero de filas y lo reducen a un único valor.

Vamos a montar una tabla pequeña para experimentar:

Cinco filas entran, una fila sale. Ese es el modelo mental completo: las funciones de agregación en SQLite aplastan filas para devolver un resumen. Si no hay un GROUP BY, ese resumen abarca todas las filas del resultado.

COUNT: filas vs valores

COUNT tiene tres variantes, y la diferencia importa:

  • COUNT(*) cuenta filas. Incluye los NULL. Siempre devuelve un número.
  • COUNT(columna) cuenta los valores no nulos de esa columna.
  • COUNT(DISTINCT columna) cuenta los valores únicos no nulos.

Tenemos cinco filas, tres con amount y tres clientes distintos. Si alguna vez ves que COUNT(amount) da un número menor que COUNT(*), ya sabes por qué: los NULL no se cuentan.

SUM, AVG, MIN y MAX en SQLite

Las funciones de agregación aritméticas se comportan como esperarías, salvo por una regla silenciosa: todas ignoran los NULL:

AVG calcula (10 + 20 + 30) / 3 = 20.0, no 60 / 4 = 15.0. El denominador es el número de valores no NULL. Si no es lo que buscas —por ejemplo, si prefieres tratar los datos faltantes como cero—, conviene indicarlo de forma explícita:

MIN y MAX también funcionan con texto y fechas: comparan de forma lexicográfica en el caso del texto, y como cadenas ISO cuando usas el formato estándar de fecha.

Diferencia entre SUM y TOTAL en SQLite

SQLite incluye una segunda función de agregación parecida a la suma, TOTAL, que resuelve dos detalles molestos de SUM:

  • SUM sobre cero filas devuelve NULL. TOTAL devuelve 0.0.
  • SUM cuando todos los valores son NULL devuelve NULL. TOTAL devuelve 0.0.
  • TOTAL siempre devuelve un número de punto flotante, así que nunca se desborda como pasa con la aritmética de enteros.

¿La contraparte? TOTAL no es estándar, y el hecho de que siempre retorne REAL puede pillarte por sorpresa si esperabas un entero. Úsalo cuando "cero filas significa cero" sea la respuesta correcta para tu aplicación, y quédate con SUM cuando necesites el comportamiento del SQL estándar.

DISTINCT dentro de funciones de agregación

DISTINCT se puede usar dentro de cualquier función de agregación, no solo en COUNT. Elimina los valores duplicados antes de que se ejecute la agregación:

SUM(amount) suma el amount de todas las filas. SUM(DISTINCT amount) suma cada valor único una sola vez, lo cual sirve para casos como "total de importes únicos de facturas", aunque casi nunca es lo que buscas. La que sí se usa a menudo es COUNT(DISTINCT customer).

FILTER: agregar solo un subconjunto

Cuando quieres agregar únicamente algunas filas, lo primero que se te ocurre es usar WHERE. El problema es que WHERE filtra toda la consulta, así que no puedes combinar "contar pedidos pagados" y "contar reembolsos" en la misma sentencia. Aquí es donde entra la cláusula FILTER en SQLite:

Cada cláusula FILTER (WHERE ...) aplica solo a ese agregado en concreto. Una sola pasada por la tabla, varios cortes resumidos. Antes de que existiera FILTER, había que escribir SUM(CASE WHEN status = 'paid' THEN amount END) — la misma idea, pero con más tecleo.

GROUP_CONCAT en SQLite: concatenar cadenas

GROUP_CONCAT es el bicho raro de la familia. En lugar de devolver un número, concatena los valores en una sola cadena:

El separador por defecto es la coma. Si quieres otro, pásalo como segundo argumento. El orden no está garantizado a menos que envuelvas la llamada como GROUP_CONCAT(tag ORDER BY tag) — muy útil cuando el resultado se muestra en una interfaz y necesitas que sea estable.

Agregaciones sin GROUP BY en SQLite

Todos los ejemplos anteriores que usaban funciones de agregación sin GROUP BY devolvieron exactamente una fila. Esa es la regla: un SELECT con agregaciones y sin GROUP BY es un resumen de una sola fila sobre toda la tabla (después de aplicar el WHERE).

Puedes combinar agregaciones sin problema:

Lo que no puedes hacer es mezclar columnas no agregadas con funciones de agregación y esperar resultados coherentes:

-- Permitido por SQLite, pero el valor de `customer` es arbitrario.
SELECT customer, SUM(amount) FROM orders;

SQLite no te dará error aquí (otras bases de datos sí), pero mostrará el nombre de un cliente cualquiera junto al total. Si lo que quieres es un total por cliente, necesitas GROUP BY — y de eso va la siguiente página.

Siguiente: GROUP BY y HAVING en SQLite

Las funciones de agregación sobre toda la tabla responden a "cuánto hay en total". Las agregaciones por grupo — por cliente, por mes, por estado — son las que responden a las preguntas realmente interesantes. Con GROUP BY divides las filas en grupos antes de agregar, y con HAVING filtras sobre el resultado ya agregado. Vamos a ello.

Preguntas frecuentes

¿Qué son las funciones de agregación en SQLite?

Son funciones que toman varias filas y devuelven un único valor resumen. Las que vienen incorporadas son COUNT, SUM, AVG, MIN, MAX, TOTAL y GROUP_CONCAT. Si no usas GROUP BY, todo el resultado se reduce a una sola fila.

¿Cuál es la diferencia entre SUM y TOTAL en SQLite?

Las dos suman, pero SUM devuelve NULL cuando todas las entradas son NULL y usa aritmética entera siempre que puede (lo que puede provocar overflow). TOTAL, en cambio, devuelve siempre un número en coma flotante y da 0.0 cuando no hay filas. Usa TOTAL si necesitas garantizar un resultado numérico, y SUM cuando te interese respetar el comportamiento estándar de SQL.

¿Cómo cuento valores únicos en SQLite?

Mete DISTINCT dentro de la llamada: COUNT(DISTINCT customer_id). Eso cuenta los valores únicos que no sean NULL. COUNT(column) a secas cuenta los valores no nulos incluyendo duplicados, y COUNT(*) cuenta todas las filas, haya NULL o no.

¿Las funciones de agregación de SQLite ignoran los NULL?

Sí: todas las agregaciones excepto COUNT(*) saltan las entradas NULL. Por ejemplo, AVG divide entre la cantidad de valores no nulos, no entre el total de filas. La excepción es COUNT(*), que cuenta filas y no valores, así que ahí los NULL sí entran.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR