GROUP BY y HAVING
GROUP BY es el equivalente SQL de df.groupby() en pandas. Agrupa filas por una columna y aplica
funciones de agregación a cada grupo: total por ciudad, promedio por tipo, conteo por categoría. Es la
herramienta más poderosa para análisis de datos.
Concepto teórico
¿Qué hace GROUP BY?
Sin GROUP BY, las funciones de agregación (COUNT, SUM, AVG) resumen TODA la tabla en una sola fila. Con GROUP BY, agrupan las filas por los valores de una columna y calculan la agregación para CADA grupo:
-- Sin GROUP BY: una sola fila con el total SELECT COUNT(*), SUM(saldo) FROM clientes; -- → 5 | 1477000 -- Con GROUP BY: una fila POR CADA ciudad SELECT ciudad, COUNT(*), SUM(saldo) FROM clientes GROUP BY ciudad; -- → Buenos Aires | 2 | 1040000 -- → Córdoba | 1 | 320000 -- → Rosario | 1 | 45000 -- → Mendoza | 1 | 72000
La regla de oro de GROUP BY
nombre en el SELECT sin agregarlo
ni agruparlo, SQL no sabe qué nombre mostrar para el grupo. Esto da error en la mayoría de los motores
(PostgreSQL, MySQL strict, SQL Server).-- ✅ CORRECTO: ciudad está en GROUP BY SELECT ciudad, COUNT(*) FROM clientes GROUP BY ciudad; -- ❌ INCORRECTO: nombre no está en GROUP BY ni en agregación -- SELECT ciudad, nombre, COUNT(*) FROM clientes GROUP BY ciudad; -- Error: "nombre" no está en GROUP BY -- ✅ CORRECTO: nombre dentro de agregación SELECT ciudad, GROUP_CONCAT(nombre) as nombres, COUNT(*) FROM clientes GROUP BY ciudad;
HAVING — filtrar después de agrupar
HAVING es como WHERE pero para grupos. La diferencia:
- WHERE filtra FILAS individuales ANTES de agrupar
- HAVING filtra GRUPOS DESPUÉS de agrupar
-- WHERE: solo incluir clientes activos (filtra filas) -- HAVING: solo mostrar ciudades con más de 2 clientes (filtra grupos) SELECT ciudad, COUNT(*) AS cantidad, AVG(saldo) AS promedio FROM clientes WHERE activo = 1 -- filtra filas ANTES de agrupar GROUP BY ciudad HAVING COUNT(*) >= 2 -- filtra grupos DESPUÉS de agrupar ORDER BY promedio DESC;
Orden de ejecución de SQL
SQL NO se ejecuta en el orden en que lo escribís. El orden real es:
| Orden escrito | Orden de ejecución |
|---|---|
| 1. SELECT | 1. FROM — de qué tabla |
| 2. FROM | 2. WHERE — filtrar filas |
| 3. WHERE | 3. GROUP BY — agrupar |
| 4. GROUP BY | 4. HAVING — filtrar grupos |
| 5. HAVING | 5. SELECT — qué columnas |
| 6. ORDER BY | 6. ORDER BY — ordenar |
| 7. LIMIT | 7. LIMIT — limitar |
Entender este orden te explica por qué WHERE no puede usar alias del SELECT, y por qué HAVING puede usar funciones de agregación pero WHERE no.
GROUP BY con múltiples columnas
Podés agrupar por más de una columna: GROUP BY ciudad, tipo crea un grupo para cada combinación
única de ciudad+tipo.
df.groupby("col").agg(...), en SQL es GROUP BY col.
Ejemplos explicados paso a paso
Ejemplo 1: GROUP BY básico — por ciudad
Hacé clic en ▶ Ejecutar
Ejemplo 2: HAVING — filtrar grupos
Hacé clic en ▶ Ejecutar
Ejemplo 3: WHERE + GROUP BY + HAVING (el combo completo)
Hacé clic en ▶ Ejecutar
Ejemplo 4: GROUP BY con múltiples columnas
Hacé clic en ▶ Ejecutar
Ejemplo 5: GROUP BY con CASE WHEN — agrupar por categoría calculada
Hacé clic en ▶ Ejecutar
Referencia rápida
| Concepto | Sintaxis | Cuándo usar |
|---|---|---|
| Agrupar | GROUP BY col |
Estadísticas por categoría |
| Multi-grupo | GROUP BY c1, c2 |
Combinaciones (ciudad+mes) |
| Filtrar grupos | HAVING condición_agg |
Solo grupos que cumplan |
| Regla de oro | Todo en SELECT → GROUP BY o agregación | SIEMPRE |
| WHERE vs HAVING | WHERE | HAVING |
|---|---|---|
| Cuándo filtra | ANTES de agrupar | DESPUÉS de agrupar |
| Qué filtra | Filas individuales | Grupos completos |
| Puede usar agregaciones? | NO | SÍ |
| Ejemplo | WHERE activo = 1 |
HAVING COUNT(*) > 2 |
Ejercicios
Ejercicio 1: GROUP BY simple
Contá cuántos clientes hay por ciudad. Debe incluir Buenos Aires.
Hacé clic en ▶ Ejecutar
Ejercicio 2: SUM por grupo
Calculá el saldo total por ciudad. Debe incluir 1040000 (BsAs).
Hacé clic en ▶ Ejecutar
Ejercicio 3: AVG por grupo
Calculá el score promedio por ciudad (redondeado). Debe incluir 765 (BsAs).
Hacé clic en ▶ Ejecutar
Ejercicio 4: HAVING básico
Mostrá solo ciudades con 2 o más clientes. Debe incluir Córdoba.
Hacé clic en ▶ Ejecutar
Ejercicio 5: WHERE + GROUP BY
Contá clientes ACTIVOS por ciudad. Debe incluir 3 (BsAs activos).
Hacé clic en ▶ Ejecutar
Ejercicio 6: Transacciones por tipo
Agrupá transacciones por tipo: cantidad y monto total. Ordená por monto total DESC. Debe incluir
compra.
Hacé clic en ▶ Ejecutar
Ejercicio 7: GROUP BY múltiples columnas
Agrupá transacciones por mes Y tipo. Debe incluir 2025-01.
Hacé clic en ▶ Ejecutar
Ejercicio 8: WHERE + GROUP BY + HAVING + ORDER BY
De clientes activos, agrupá por ciudad, mostrá solo ciudades con saldo total > $200K, ordená por saldo DESC.
Debe incluir Buenos Aires.
Hacé clic en ▶ Ejecutar
Ejercicio 9: GROUP BY con CASE WHEN
Agrupá clientes por categoría de score (Excelente/Bueno/Regular/Bajo) y mostrá cantidad y saldo promedio por
categoría. Debe incluir Excelente.
Hacé clic en ▶ Ejecutar
Ejercicio 10: Reporte gerencial por ciudad
Generá un reporte por ciudad con: cantidad de clientes, % del total, saldo total, saldo promedio, score
promedio, y cantidad de premium (score>=700). Solo ciudades con 2+ clientes. Ordená por saldo total DESC. Debe
incluir premium.
Hacé clic en ▶ Ejecutar
Resumen y conexión
GROUP BY colagrupa filas y permite calcular agregaciones POR grupo.- Regla de oro: toda columna en SELECT que no esté en una agregación DEBE estar en GROUP BY.
HAVINGfiltra GRUPOS (después de agrupar).WHEREfiltra FILAS (antes).- Múltiples columnas en GROUP BY:
GROUP BY c1, c2agrupa por combinación. - Orden de ejecución: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.
GROUP BY CASE WHEN ...agrupa por categorías calculadas.
En la siguiente lección (07 · JOINs INNER) vas a aprender a combinar datos de múltiples tablas — la operación que conecta clientes con sus cuentas, transacciones con productos, y más.
Recursos: W3Schools — GROUP BY