QuieroProgramar por Rodri Gonzalez
SQL · Lección 06 de 15

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.

90–110 min Prerrequisitos: SQL 05
01

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

LA REGLA MÁS IMPORTANTE DE SQL: toda columna en el SELECT que NO esté dentro de una función de agregación DEBE estar en el GROUP BY. Si ponés 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;
Pensalo así: GROUP BY crea "grupos" de filas. Cada grupo se resume en UNA fila del resultado. Si agrupás por ciudad, BsAs tiene 3 clientes — ¿qué nombre mostrás para esa fila? No tiene sentido. Por eso, las columnas no agrupadas deben estar dentro de COUNT, SUM, AVG, etc.

HAVING — filtrar después de agrupar

HAVING es como WHERE pero para grupos. La diferencia:

-- 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;
Regla HAVING: en HAVING solo podés usar funciones de agregación o columnas que estén en el GROUP BY. No podés filtrar por columnas individuales en HAVING — para eso está WHERE.

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.

En el trabajo: GROUP BY es probablemente la cláusula SQL más importante para un analista. "Ventas por mes", "saldo promedio por segmento", "cantidad de transacciones por tipo y ciudad", "clientes nuevos por semana" — todo es GROUP BY. En pandas hacés df.groupby("col").agg(...), en SQL es GROUP BY col.
02

Ejemplos explicados paso a paso

Ejemplo 1: GROUP BY básico — por ciudad

ejemplo_01_groupby.sqlSQL

        
Hacé clic en ▶ Ejecutar

Ejemplo 2: HAVING — filtrar grupos

ejemplo_02_having.sqlSQL

        
Hacé clic en ▶ Ejecutar

Ejemplo 3: WHERE + GROUP BY + HAVING (el combo completo)

ejemplo_03_combo.sqlSQL

        
Hacé clic en ▶ Ejecutar

Ejemplo 4: GROUP BY con múltiples columnas

ejemplo_04_multi.sqlSQL

        
Hacé clic en ▶ Ejecutar

Ejemplo 5: GROUP BY con CASE WHEN — agrupar por categoría calculada

ejemplo_05_case_group.sqlSQL

        
Hacé clic en ▶ Ejecutar
03

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
Ejemplo WHERE activo = 1 HAVING COUNT(*) > 2
04

Ejercicios

Nivel 1 · Básico

Ejercicio 1: GROUP BY simple

Contá cuántos clientes hay por ciudad. Debe incluir Buenos Aires.

ejercicio_01.sqlDebe incluir "Buenos Aires"

          
Hacé clic en ▶ Ejecutar
Nivel 1 · Básico

Ejercicio 2: SUM por grupo

Calculá el saldo total por ciudad. Debe incluir 1040000 (BsAs).

ejercicio_02.sqlDebe incluir "1040000"

          
Hacé clic en ▶ Ejecutar
Nivel 1 · Básico

Ejercicio 3: AVG por grupo

Calculá el score promedio por ciudad (redondeado). Debe incluir 765 (BsAs).

ejercicio_03.sqlDebe incluir "765"

          
Hacé clic en ▶ Ejecutar
Nivel 2 · Intermedio

Ejercicio 4: HAVING básico

Mostrá solo ciudades con 2 o más clientes. Debe incluir Córdoba.

ejercicio_04.sqlDebe incluir "Córdoba"

          
Hacé clic en ▶ Ejecutar
Nivel 2 · Intermedio

Ejercicio 5: WHERE + GROUP BY

Contá clientes ACTIVOS por ciudad. Debe incluir 3 (BsAs activos).

ejercicio_05.sqlDebe incluir "3"

          
Hacé clic en ▶ Ejecutar
Nivel 2 · Intermedio

Ejercicio 6: Transacciones por tipo

Agrupá transacciones por tipo: cantidad y monto total. Ordená por monto total DESC. Debe incluir compra.

ejercicio_06.sqlDebe incluir "compra"

          
Hacé clic en ▶ Ejecutar
Nivel 3 · Avanzado

Ejercicio 7: GROUP BY múltiples columnas

Agrupá transacciones por mes Y tipo. Debe incluir 2025-01.

ejercicio_07.sqlDebe incluir "2025-01"

          
Hacé clic en ▶ Ejecutar
Nivel 3 · Avanzado

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.

ejercicio_08.sqlDebe incluir "Buenos Aires"

          
Hacé clic en ▶ Ejecutar
Nivel 3 · Avanzado

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.

ejercicio_09.sqlDebe incluir "Excelente"

          
Hacé clic en ▶ Ejecutar
Nivel 4 · Desafío

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.

ejercicio_10.sqlDebe incluir "premium"

          
Hacé clic en ▶ Ejecutar
05

Resumen y conexión

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