GROUP BY: Agrupar y resumir datos

Lectura
20 min~5 min lectura

Concepto clave

Imagina que tienes una lista de ventas de tu tienda. Quieres saber cuánto vendió cada vendedor, o cuántas unidades se vendieron por producto. GROUP BY es la herramienta que te permite agrupar filas que comparten un valor común y luego aplicar funciones de resumen (como SUM, COUNT, AVG) a cada grupo.

En la vida real, piensa en un montón de recibos de compras. Si quieres saber el total gastado por cada cliente, agrupas los recibos por cliente y sumas los montos. Eso es exactamente lo que hace GROUP BY en SQL.

La sintaxis básica es: SELECT columna_agrupada, función_resumen(columna) FROM tabla GROUP BY columna_agrupada. La columna que aparece en SELECT debe estar en GROUP BY o ser una función de resumen.

Cómo funciona en la práctica

Supón que tienes una tabla llamada ventas con las columnas: id, vendedor, producto, cantidad, precio. Quieres saber el total vendido por cada vendedor.

Primero, piensa en los grupos: cada vendedor único es un grupo. Luego, para cada grupo, sumas el precio * cantidad (ingreso). La consulta sería:

SELECT vendedor, SUM(cantidad * precio) AS total_ingresos
FROM ventas
GROUP BY vendedor;

Esto devuelve una fila por cada vendedor con su total. Si además quieres filtrar solo vendedores con ventas mayores a 1000, usas HAVING (no WHERE, porque WHERE filtra antes de agrupar):

SELECT vendedor, SUM(cantidad * precio) AS total_ingresos
FROM ventas
GROUP BY vendedor
HAVING total_ingresos > 1000;

Código en acción

Vamos a crear una tabla de ejemplo y ejecutar consultas. Primero, crea la tabla e inserta datos:

CREATE TABLE ventas (
    id INT PRIMARY KEY,
    vendedor VARCHAR(50),
    producto VARCHAR(50),
    cantidad INT,
    precio DECIMAL(10,2)
);

INSERT INTO ventas VALUES
(1, 'Ana', 'Laptop', 2, 15000),
(2, 'Luis', 'Mouse', 5, 200),
(3, 'Ana', 'Teclado', 3, 800),
(4, 'Luis', 'Laptop', 1, 15000),
(5, 'Sofia', 'Monitor', 2, 4000);

Ahora, consulta el total de ingresos por vendedor:

SELECT vendedor, SUM(cantidad * precio) AS total_ingresos
FROM ventas
GROUP BY vendedor;

Resultado esperado:

vendedor | total_ingresos
Ana      | 32400
Luis     | 16000
Sofia    | 8000

Si quieres contar cuántas ventas hizo cada vendedor:

SELECT vendedor, COUNT(*) AS num_ventas
FROM ventas
GROUP BY vendedor;

Resultado:

vendedor | num_ventas
Ana      | 2
Luis     | 2
Sofia    | 1

Errores comunes

  1. Olvidar incluir todas las columnas no agregadas en GROUP BY: Si SELECT tiene una columna que no está en GROUP BY y no es función de resumen, SQL arrojará error. Solución: asegúrate de que cada columna en SELECT esté en GROUP BY o sea agregada.
  2. Usar WHERE en lugar de HAVING para filtrar grupos: WHERE filtra filas antes de agrupar; HAVING filtra después. Si quieres filtrar por resultado de agregación (ej. SUM > 100), usa HAVING.
  3. Confundir COUNT(*) con COUNT(columna): COUNT(*) cuenta todas las filas del grupo, incluyendo NULLs. COUNT(columna) cuenta solo las filas donde columna no es NULL. Úsalos según necesites.
  4. No usar alias en funciones de resumen: El resultado de SUM(cantidad) se muestra como 'SUM(cantidad)'. Usa alias (AS) para darle un nombre claro.
  5. Agrupar por columnas con muchos valores únicos: Si agrupas por una columna como 'id', cada grupo tendrá una sola fila, y GROUP BY no tiene sentido. Asegúrate de agrupar por columnas que tengan valores repetidos.

Checklist de dominio

  • Puedo escribir una consulta SELECT con GROUP BY para agrupar datos por una columna.
  • Puedo usar funciones de resumen (SUM, COUNT, AVG, MIN, MAX) dentro de GROUP BY.
  • Puedo usar HAVING para filtrar grupos después de agrupar.
  • Puedo explicar la diferencia entre WHERE y HAVING.
  • Puedo evitar el error de columnas no agregadas fuera de GROUP BY.
  • Puedo agrupar por múltiples columnas (ej. GROUP BY vendedor, producto).
  • Puedo crear una consulta que devuelva el total de ventas por vendedor y producto.

Ejercicio: Reporte de ventas por categoría

Tu tarea es generar un reporte de ventas agrupado por categoría de producto. Usa la tabla productos y ventas que se definen a continuación.

Paso 1: Crear las tablas

CREATE TABLE productos (
    id INT PRIMARY KEY,
    nombre VARCHAR(50),
    categoria VARCHAR(50),
    precio DECIMAL(10,2)
);

CREATE TABLE ventas (
    id INT PRIMARY KEY,
    producto_id INT,
    cantidad INT,
    fecha DATE,
    FOREIGN KEY (producto_id) REFERENCES productos(id)
);

INSERT INTO productos VALUES
(1, 'Laptop', 'Electrónica', 15000),
(2, 'Mouse', 'Electrónica', 200),
(3, 'Teclado', 'Electrónica', 800),
(4, 'Camisa', 'Ropa', 500),
(5, 'Pantalón', 'Ropa', 700);

INSERT INTO ventas VALUES
(1, 1, 2, '2024-01-10'),
(2, 2, 5, '2024-01-11'),
(3, 3, 3, '2024-01-12'),
(4, 4, 4, '2024-01-13'),
(5, 5, 1, '2024-01-14'),
(6, 1, 1, '2024-01-15');

Paso 2: Escribir la consulta

Escribe una consulta SQL que devuelva: categoria, total_ingresos (suma de cantidad * precio) y num_ventas (conteo de ventas) para cada categoría. Ordena el resultado por total_ingresos descendente.

Paso 3: Verificar el resultado

El resultado esperado es:

categoria    | total_ingresos | num_ventas
Electrónica  | 32900          | 4
Ropa         | 2700           | 2

Mini-rúbrica de evaluación:

  • La consulta usa GROUP BY correctamente (1 punto)
  • Usa SUM y COUNT con alias (1 punto)
  • Incluye JOIN entre ventas y productos (1 punto)
  • Ordena por total_ingresos DESC (1 punto)
  • El resultado coincide con el esperado (1 punto)

Entregable: La consulta SQL completa como texto.

Pistas
  • Recuerda que necesitas unir las tablas ventas y productos usando producto_id = productos.id
  • Para calcular el ingreso, multiplica cantidad por el precio del producto (ventas.cantidad * productos.precio)
  • Usa ORDER BY total_ingresos DESC al final