Saltar al contenido
Apuntes SQL Conquer Blocks
Teoría Clase 04a Tema 04

Funciones agregadas y agrupación — Conceptos

Las funciones agregadas calculan un único valor a partir de múltiples filas: cuántas hay, cuánto suman, cuál es la media, el mínimo y el máximo. Combinadas con GROUP BY se convierten en la herramienta principal para analizar datos por segmentos, y con HAVING se pueden filtrar esos segmentos con precisión quirúrgica.

#COUNT#SUM#AVG#MIN#MAX#GROUP BY#HAVING#GROUP_CONCAT#WITH ROLLUP#CASE WHEN
§ 01

Resumen rápido

Las funciones agregadas calculan un único valor a partir de múltiples filas: cuántas hay, cuánto suman, cuál es la media, el mínimo y el máximo. Combinadas con GROUP BY se convierten en la herramienta principal para analizar datos por segmentos, y con HAVING se pueden filtrar esos segmentos con precisión quirúrgica.

§ 02

Conceptos clave

Función agregada

Función que recibe un conjunto de filas y devuelve un único valor de resumen: COUNT, SUM, AVG, MIN o MAX. Su resultado depende de todas las filas procesadas, no de una sola.

COUNT

Cuenta filas. COUNT(*) cuenta todas las filas, COUNT(columna) cuenta solo las no nulas, COUNT(DISTINCT columna) cuenta los valores únicos eliminando duplicados.

SUM

Suma todos los valores numéricos de una columna. No funciona con texto ni con booleanos. Ignora los valores nulos.

AVG

Calcula el promedio aritmético de una columna numérica. Los valores nulos se ignoran: no arrastran el promedio hacia cero ni cuentan como divisor.

MIN / MAX

Devuelven el valor mínimo o máximo de una columna. Funcionan con números, fechas y texto (ordenamiento alfabético). No funcionan con booleanos.

GROUP BY

Agrupa las filas que comparten el mismo valor en una o varias columnas. Todas las columnas del SELECT que no sean funciones agregadas deben aparecer también en el GROUP BY.

HAVING

Filtra grupos después de que GROUP BY los ha formado. Solo puede usarse con funciones agregadas. A diferencia de WHERE, actúa sobre grupos completos, no sobre filas individuales.

GROUP_CONCAT

Concatena los valores de una columna dentro de cada grupo en una cadena de texto. Acepta un separador personalizado (SEPARATOR) y puede combinarse con DISTINCT para eliminar duplicados.

WITH ROLLUP

Modificador de GROUP BY que añade automáticamente filas de subtotales por nivel de agrupación y una fila de total general al final. Los subtotales se identifican porque sus columnas de agrupación aparecen como NULL.

CASE WHEN

Expresión condicional que evalúa casos en orden y devuelve el valor del primer caso que se cumple. Se cierra con END y puede asignarse a una columna nueva con AS. Equivale a un bloque if/elif/else en programación.

Subconsulta con agregado

Consulta anidada dentro de un WHERE o SELECT que primero calcula un valor de resumen (como el promedio global) y luego lo usa como referencia en la consulta exterior.

Orden lógico de ejecución

SQL procesa las cláusulas en este orden interno: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. No es el orden en que se escriben, sino el orden en que el motor los evalúa.

§ 03

Contenido de la clase

De filas a resúmenes: qué hace una función agregada

Una consulta ordinaria devuelve una fila por cada fila de la tabla. Una función agregada hace lo contrario: toma todas las filas (o un subconjunto) y colapsa el resultado en un único valor. Eso lo convierte en la herramienta fundamental para responder preguntas como "¿cuántas películas hay?", "¿cuánto suma el coste total?" o "¿cuál es la duración media?".

Las cinco funciones agregadas básicas cubren la mayoría de los análisis numéricos. Todas se escriben después de SELECT, igual que cualquier otra columna, y pueden renombrarse con AS para que el resultado tenga un nombre legible.

COUNT: contar con precisión

COUNT tiene tres variantes y cada una cuenta cosas distintas. Elegir mal entre ellas es el error más frecuente cuando se trabaja con columnas que pueden tener nulos.

VarianteQué cuentaCuándo usarla
COUNT(*)Todas las filas, incluidas las que tengan nulosContar registros totales de una tabla
COUNT(columna)Solo las filas donde esa columna no es NULLVerificar cuántos registros tienen ese dato
COUNT(DISTINCT columna)Los valores únicos, eliminando duplicadosSaber cuántos valores distintos existen

SUM, AVG, MIN y MAX

SUM acumula todos los valores numéricos de una columna. AVG calcula la media aritmética ignorando los nulos, lo que significa que los campos vacíos no arrastran el promedio hacia cero. MIN y MAX devuelven los extremos de una columna: funcionan con números, fechas y texto (orden alfabético), pero no con booleanos.

  • SUM y AVG solo tienen sentido en columnas numéricas. Aplicarlas sobre texto provoca un error o un resultado incoherente.
  • AVG ignora los nulos: si 100 filas tienen valor y 20 son NULL, el promedio se calcula sobre 100, no sobre 120.
  • MIN y MAX en columnas de texto devuelven el valor más temprano y más tardío en el alfabeto, lo que puede ser útil para encontrar el primer y último nombre de una lista ordenada.

GROUP BY: analizar por segmentos

GROUP BY convierte el análisis de "toda la tabla" en "un análisis por cada grupo". En lugar de devolver el total de películas de toda la base de datos, puede devolver el total por clasificación, por año, por idioma o por cualquier otra columna.

Hay dos reglas que no tienen excepción. Si se ignoran, MySQL devolverá un error o un resultado incorrecto.

  1. Todas las columnas del SELECT que no sean funciones agregadas deben aparecer también en el GROUP BY. Si seleccionas "rating" y "COUNT(*)", tienes que agrupar por "rating".
  2. El orden de los grupos no está garantizado. Si necesitas los resultados en un orden concreto, añade siempre ORDER BY después del GROUP BY.

HAVING: filtrar grupos, no filas

WHERE filtra filas antes de que se formen los grupos. HAVING filtra grupos una vez ya están formados. La diferencia es importante: WHERE no puede referenciar funciones agregadas porque se ejecuta antes de que existan; HAVING sí puede, porque actúa después de GROUP BY.

WHEREHAVING
Cuándo actúaAntes de GROUP BYDespués de GROUP BY
FiltraFilas individualesGrupos completos
Puede usar funciones agregadasNo
Caso de uso típicorating = 'PG'COUNT(*) > 200

Un patrón habitual es combinar WHERE y HAVING en la misma consulta: WHERE reduce las filas antes de agrupar (más eficiente), y HAVING elimina los grupos que no interesan después de agregarse.

Funciones avanzadas: GROUP_CONCAT, WITH ROLLUP y CASE WHEN

Más allá de los cinco agregados básicos, SQL ofrece herramientas para construir reportes más expresivos. Las tres más útiles para análisis y presentación de datos son GROUP_CONCAT, WITH ROLLUP y CASE WHEN.

  • GROUP_CONCAT: concatena todos los valores de una columna dentro de cada grupo en una sola cadena de texto, separados por el carácter que se indique. Con DISTINCT elimina los duplicados antes de concatenar. Es ideal para generar listas compactas en reportes.
  • WITH ROLLUP: se añade al final del GROUP BY y genera automáticamente filas de subtotales por cada nivel de agrupación, más una fila de total general. Las columnas de agrupación aparecen como NULL en las filas de subtotal; IFNULL permite reemplazar esos NULL por una etiqueta legible.
  • CASE WHEN: crea una nueva columna calculada en función de condiciones. La estructura es CASE WHEN condición THEN valor ... ELSE valor_por_defecto END. Se usa habitualmente para segmentar datos en categorías (alto/medio/bajo) o para reetiquetado.

El orden lógico de ejecución

SQL no ejecuta las cláusulas en el orden en que se escriben. El motor sigue un orden interno independiente de cómo esté redactada la consulta. Entender este orden explica por qué WHERE no puede filtrar por alias definidos en SELECT, y por qué HAVING debe ir después de GROUP BY.

  1. FROM: identifica la tabla o las tablas de origen.
  2. WHERE: filtra las filas que no cumplen la condición.
  3. GROUP BY: forma los grupos a partir de las filas que quedaron.
  4. HAVING: elimina los grupos que no cumplen la condición agregada.
  5. SELECT: calcula las columnas y los agregados del resultado final.
  6. ORDER BY: ordena las filas del resultado.
  7. LIMIT: recorta el número de filas devueltas.
§ 04

Código y ejemplos

Las cinco funciones agregadas

SQL
-- COUNT: contar filas, valores no nulos y valores únicos
SELECT COUNT(*)                AS total_filas,
       COUNT(replacement_cost) AS con_coste,
       COUNT(DISTINCT rating)  AS ratings_unicos
FROM film;

-- SUM y AVG: suma y media de una columna numérica
SELECT SUM(replacement_cost) AS coste_total,
       AVG(length)           AS duracion_media
FROM film;

-- MIN y MAX: extremos de una columna
SELECT MIN(length) AS pelicula_mas_corta,
       MAX(length) AS pelicula_mas_larga
FROM film;

Todas las funciones agregadas se pueden combinar en un único SELECT. El resultado siempre es una sola fila cuando no hay GROUP BY.

GROUP BY con COUNT y AVG

SQL
-- Cuántas películas hay en cada clasificación
SELECT rating,
       COUNT(*) AS total
FROM film
GROUP BY rating
ORDER BY total DESC;

-- Tarifa media de alquiler por clasificación
SELECT rating,
       AVG(rental_rate) AS tarifa_media
FROM film
GROUP BY rating
ORDER BY tarifa_media DESC;

La columna que no es un agregado (rating) debe aparecer en GROUP BY. ORDER BY permite ordenar por el agregado calculado.

HAVING: filtrar grupos por condición agregada

SQL
-- Solo las clasificaciones con más de 200 películas
SELECT rating,
       COUNT(*) AS total
FROM film
GROUP BY rating
HAVING COUNT(*) > 200
ORDER BY total DESC;

-- Características especiales asociadas a películas más largas que la media
SELECT special_features,
       AVG(length) AS duracion_media
FROM film
GROUP BY special_features
HAVING AVG(length) > 115
ORDER BY duracion_media DESC;

HAVING se escribe después de GROUP BY y antes de ORDER BY. Solo puede contener condiciones que impliquen funciones agregadas.

CASE WHEN: segmentar datos en categorías

SQL
-- Segmentar películas en tres grupos por coste de reemplazo
SELECT CASE
         WHEN replacement_cost < 15           THEN 'Bajo'
         WHEN replacement_cost BETWEEN 15 AND 20 THEN 'Medio'
         ELSE                                      'Alto'
       END                      AS segmento_coste,
       COUNT(*)                 AS cantidad,
       AVG(rental_rate)         AS tarifa_media,
       AVG(length)              AS duracion_media
FROM film
GROUP BY segmento_coste
ORDER BY cantidad DESC;

CASE WHEN genera una nueva columna calculada que puede usarse directamente en GROUP BY. El alias asignado con END AS es el que se referencia después.

§ 05

Errores comunes

Incluir en SELECT una columna que no es un agregado y no está en GROUP BY. MySQL puede permitirlo en algunos modos, pero devuelve un valor arbitrario, no el correcto.
Usar WHERE para filtrar por una función agregada en lugar de HAVING. WHERE se ejecuta antes de GROUP BY y no tiene acceso a los valores calculados por COUNT, SUM, etc.
Olvidar ORDER BY después de GROUP BY y asumir que los grupos vendrán ordenados. El orden de los grupos no está garantizado sin ORDER BY explícito.
Confundir COUNT(*) con COUNT(columna) en tablas con nulos. Si la columna tiene nulos, COUNT(columna) devolverá un número menor que COUNT(*), lo que puede llevar a conclusiones erróneas.
Aplicar SUM o AVG sobre columnas de texto. El resultado es 0 o NULL sin aviso de error claro, por lo que el error puede pasar desapercibido.
§ 06

Buenas prácticas

Nombra siempre el resultado de un agregado con AS para que la columna tenga un nombre descriptivo y no aparezca como "COUNT(*)" o "AVG(length)" en el resultado.
Usa WHERE para reducir las filas antes de GROUP BY siempre que puedas: es más eficiente que HAVING, porque descarta filas antes de calcular los agregados.
Reserva HAVING exclusivamente para condiciones que involucren funciones agregadas. Si la condición puede ir en WHERE, ponla en WHERE.
Añade siempre ORDER BY cuando uses GROUP BY para que el resultado sea reproducible y predecible, independientemente de cómo MySQL decida ordenar internamente los grupos.
Antes de escribir una consulta con GROUP BY, pregúntate cuál es la unidad de análisis (por rating, por año, por categoría) y asegúrate de que esa columna está tanto en SELECT como en GROUP BY.
§ 07

Ejercicios

  1. Usando la tabla film de Sakila, cuenta cuántas películas hay en total con COUNT(*) y cuántos tipos de clasificación distintos hay con COUNT(DISTINCT rating).
  2. Calcula la suma total del replacement_cost de todas las películas y la media de la duración (length). Renombra las columnas con AS.
  3. Obtén la película con menor y mayor duración usando MIN y MAX sobre la columna length.
  4. Agrupa las películas por rating y muestra cuántas hay en cada grupo (COUNT) y la tarifa media de alquiler (AVG de rental_rate). Ordena el resultado de mayor a menor por la tarifa media.
  5. Usa HAVING para mostrar solo las clasificaciones que tienen más de 190 películas.
  6. Usa CASE WHEN para segmentar las películas en "Corta" (length < 90), "Media" (90–120) y "Larga" (> 120). Muestra cuántas hay en cada segmento.
§ 08

Checklist final

  • Conozco las cinco funciones agregadas básicas: COUNT, SUM, AVG, MIN y MAX.
  • Entiendo la diferencia entre COUNT(*), COUNT(columna) y COUNT(DISTINCT columna).
  • Sé que AVG ignora los nulos al calcular el promedio.
  • Puedo escribir una consulta con GROUP BY y sé que todas las columnas no agregadas del SELECT deben estar en GROUP BY.
  • Entiendo la diferencia entre WHERE (filtra filas) y HAVING (filtra grupos).
  • Conozco el orden lógico de ejecución: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.
  • Sé crear columnas condicionales con CASE WHEN...THEN...ELSE...END.

¿Has terminado la clase?

Márcala como repasada y vuelve cuando quieras revisarla.