DBA Junior Ciberecus MX
Temas · Capítulo 2 · PF-010

Tema 10: Funciones de agregación y GROUP BY: el poder de resumir

Identificador: PF-010 | XP: 200 | Insignia: 🥇 Oro | Tier: Aprendiz
Tiempo estimado: 90-120 min | Pre-requisitos: PF-007, PF-009

🖼️ Imagen de inicio del tema

Cartoon Tema 10 - Moka con balanza de cobre y granos de cacao

[Moka con balanza azteca contando granos de cacao en grandes montones. Sofía observa los totales, Don Carlos señala los grupos, Citlalli con su codex anota los agregados.]


🎯 Aprenderás

    Funciones de agregación: COUNT, SUM, AVG, MIN, MAX. GROUP BY para agrupar filas por categoría. HAVING para filtrar grupos (vs WHERE para filtrar filas). Patrones de reportes de negocio.

🏛️ Visión mexica — Por Citlalli

"Los calpixqui mexicas reportaban al huey tlatoani con resúmenes: 'de Suchimilco llegaron 20 cargas de cacao este año'. Ese reporte era el resultado de AGRUPAR (por altépetl) y SUMAR (las cargas). GROUP BY + SUM = el reporte del calpixqui, en 500 años antes de SQL.

El poder de las funciones de agregación es exactamente ese: convertir 1000 filas de detalle en UNA fila de resumen. De 50,000 clientes individuales, una sola fila que dice 'total de clientes activos: 47,382'. Eso es lo que el negocio quiere ver: resúmenes accionables, no datos crudos."


📚 Bloque 1: Las 5 funciones de agregación básicas

SELECT COUNT() AS total_clientes FROM clientes;
SELECT COUNT(email) AS con_email FROM clientes;  -- no cuenta NULL
SELECT SUM(total) AS ingresos FROM pedidos WHERE estado = 'pagado';
SELECT AVG(precio) AS precio_promedio FROM productos;
SELECT MIN(precio) AS mas_barato, MAX(precio) AS mas_caro FROM productos;

📚 Bloque 2: GROUP BY — agrupar por categoría

-- Cuántos clientes por ciudad
SELECT ciudad, COUNT() AS total
FROM clientes
GROUP BY ciudad
ORDER BY total DESC;

Sofía pregunta: "¿Por qué GROUP BY va después de WHERE y antes de ORDER BY?"

Don Carlos: "El orden lógico de SQL es:

    FROM (de dónde sacar datos) WHERE (filtrar filas individuales) GROUP BY (agrupar filas) HAVING (filtrar grupos) SELECT (qué columnas mostrar, con agregaciones) ORDER BY (ordenar resultado) LIMIT (cuántas filas mostrar)"

📚 Bloque 3: HAVING — filtrar grupos

-- Solo ciudades con más de 5 clientes
SELECT ciudad, COUNT() AS total
FROM clientes
GROUP BY ciudad
HAVING COUNT() > 5
ORDER BY total DESC;

Don Carlos: "WHERE filtra FILAS antes de agrupar. HAVING filtra GRUPOS después de agrupar. Es la diferencia más sutil y más importante de SQL agregado."


📚 Bloque 4: Patrones de reportes de negocio

-- Ingresos por mes en 2025
SELECT DATE_FORMAT(fecha_pedido, '%Y-%m') AS mes, SUM(total) AS ingresos
FROM pedidos
WHERE YEAR(fecha_pedido) = 2025 AND estado IN ('pagado', 'enviado', 'entregado')
GROUP BY mes
ORDER BY mes;

-- Top 5 clientes por gasto SELECT c.nombre, SUM(pe.total) AS gasto_total, COUNT(pe.id) AS num_pedidos FROM clientes c INNER JOIN pedidos pe ON c.id = pe.cliente_id WHERE pe.estado != 'cancelado' GROUP BY c.id, c.nombre ORDER BY gasto_total DESC LIMIT 5;


🤖 AI Mission

Pídele: "Tengo una tabla `ventas` con 10,000 filas. Dame 3 queries de GROUP BY que un dueño de tienda pediría para entender su negocio."


⚠️ Errores típicos

    Usar WHERE en vez de HAVING para filtrar agregados. Olvidar GROUP BY cuando usas funciones de agregación. Confundir COUNT() con COUNT(columna) — el primero cuenta todas, el segundo no cuenta NULL.

🧪 LAB 10.1 — "Reportes para el dueño de Tienda Tlalli"

Reporte 1: total de clientes por estado (activo/inactivo). Reporte 2: ventas totales por método de pago. Reporte 3: top 5 categorías por ingresos (necesita JOIN). Reporte 4: promedio de productos por pedido. Reporte 5: ciudades con más de 3 clientes (HAVING).


📝 Quest 10

    ¿Qué hace COUNT()? A) Cuenta filas. B) Cuenta no-NULL. C) Solo la primera. D) Suma. ¿Cuándo usar HAVING vs WHERE? A) Son iguales. B) HAVING agrupa, WHERE filtra filas. C) WHERE agrupa. D) HAVING es para SUM. ¿Qué hace AVG? A) Suma. B) Promedio. C) Cuenta. D) Máximo. ¿GROUP BY va antes o después de WHERE? A) Antes. B) Después. C) No importa. D) Es lo mismo. ¿SELECT ciudad, COUNT() sin GROUP BY? A) Funciona. B) Error. C) Solo MySQL. D) Solo PostgreSQL. ¿MIN y MAX sirven para? A) Contar. B) Promediar. C) Valores extremos. D) Ordenar. ¿COUNT(email) cuenta NULL? A) Sí. B) No. C) A veces. D) Da error. ¿Qué hace `GROUP BY 1`? A) Agrupa por la primera columna. B) Agrupa por 1. C) Error. D) Agrupa por id. ¿`SUM(precio cantidad)`? A) Error. B) Suma el producto. C) Suma de dos cosas. D) Multiplica suma. ¿Cuándo usar COUNT(DISTINCT columna)? A) Contar duplicados. B) Contar valores únicos. C) Contar NULL. D) Contar diferentes tablas.
Abiertas:
    ¿Por qué WHERE no filtra agregaciones? Diseña un reporte de "ventas por ciudad y mes". ¿Cuándo GROUP BY ROLLUP vs GROUP BY normal?

✅ Respuestas

1-A, 2-B, 3-B, 4-B, 5-B, 6-C, 7-B, 8-A, 9-B, 10-B.


🏛️ Tras las huellas — Por Citlalli

"Los reportes del calpixqui al huey tlatoani eran el equivalente de los dashboards modernos. El tlacuilo tenía que resumir 371 altépetl en 5 minutos de lectura. Hoy un dashboard ejecutivo tiene 5 minutos de atención. El principio es el mismo: agregación + filtro + orden = decisión accionable."


📓 Cierre

1. El reporte más útil fue:
2. La diferencia WHERE/HAVING que más me costó fue:
3. Una decisión de negocio basada en estos reportes:
4. Cómo voy a usar GROUP BY en mi trabajo:

🚀 ¿Qué sigue?

Tema 11 — Subconsultas y CTEs: consultas que se leen como párrafos.