Filtra después de la agregación con HAVING y pivota tus datos con CASE WHEN dentro de funciones de agregación.
Abrir esta lección en KodokonYa conoces GROUP BY. Este módulo aborda lo que separa una consulta correcta de una profesional: el filtrado posterior a la agregación, las agregaciones condicionales y un dominio sólido del orden de evaluación. Para practicar, abre sqliteonline.com (motor SQLite) o inicia sqlite3 en una terminal: cada lección proporciona las instrucciones CREATE TABLE e INSERT que necesitas. Copia este conjunto de datos antes de ejecutar los ejemplos.
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer TEXT NOT NULL,
category TEXT NOT NULL,
amount REAL NOT NULL,
status TEXT NOT NULL
);
INSERT INTO orders (customer, category, amount, status)
VALUES
('alice', 'books', 42.0, 'paid'),
('alice', 'games', 55.0, 'paid'),
('alice', 'books', 18.5, 'refunded'),
('bruno', 'games', 70.0, 'paid'),
('bruno', 'books', 12.0, 'paid'),
('chloe', 'games', 95.0, 'paid'),
('chloe', 'books', 30.0, 'paid'),
('david', 'books', 8.0, 'refunded');El orden lógico de evaluación es la clave: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. WHERE filtra las filas antes de agrupar; HAVING filtra los grupos después de calcular las agregaciones. Por eso WHERE SUM(amount) > 90 es ilegal: en la etapa WHERE, todavía no existe ninguna suma. Aquí conservamos solo los clientes cuyo total pagado supera 90 (se espera: alice y chloe).
SELECT customer,
COUNT(*) AS nb_orders,
SUM(amount) AS total
FROM orders
WHERE status = 'paid'
GROUP BY customer
HAVING SUM(amount) > 90;El segundo patrón imprescindible es la agregación condicional. Al introducir un CASE WHEN dentro de SUM o COUNT, calculas varias métricas en una sola pasada por la tabla, donde un principiante ejecutaría tres consultas separadas. Esta es la técnica estándar para pivotar filas en columnas.
SELECT customer,
SUM(CASE WHEN category = 'books'
THEN amount ELSE 0 END) AS books_total,
SUM(CASE WHEN category = 'games'
THEN amount ELSE 0 END) AS games_total
FROM orders
WHERE status = 'paid'
GROUP BY customer;