¿Cómo saco el top 3 de cada grupo en SQL, con empates?
El reto final: saca los 3 productos más vendidos de cada mes, empates incluidos, con las cuatro decisiones del curso, y mide qué tanto cambió lo que sabes.
Curso gratis. Tu Maestro, una IA, .
Este es el reto final del curso. La tabla ventas_productos tiene las unidades vendidas de seis productos de una fonda, de enero a abril de 2025. La pregunta del negocio: ¿cuáles fueron los 3 productos más vendidos de cada mes? Usaremos puestos de competencia: los empates comparten puesto y dejan huecos, como 1, 1, 3. Entran todos los productos con puesto hasta 3, aunque el empate haga que salgan más de tres.
Todos los problemas de este curso se resolvieron con las mismas cuatro decisiones, en este orden. Tómalas antes de escribir una sola línea:
La partición
¿Dentro de qué grupo se compara cada fila? Eso va en
PARTITION BY. Si la pregunta dice "de cada", ahí está tu partición.El orden
¿Qué hace que una fila vaya antes que otra, y en qué dirección? Eso va en el
ORDER BYde adentro. Si puede haber empates, decide si necesitas un desempate.La función
¿Qué le pasa a un empate?
ROW_NUMBERlo rompe,RANKlo comparte y deja hueco,DENSE_RANKlo comparte sin hueco.El filtro
¿Dónde cortas? Nunca en
WHERE: enQUALIFY, o en elWHEREde afuera de unWITH. Y nunca conLIMIT, que corta el resultado entero.
Primero, mira las cuatro decisiones tomadas con datos que ya conoces. Abre los pasos uno por uno, y antes de abrir cada uno, intenta decir tú qué sigue. Si tu primera idea para el reto es GROUP BY mes con MAX(unidades), fíjate en lo que te daría: un solo número por mes, sin el nombre del producto y sin el segundo ni el tercer lugar. Para eso sirve una ventana: rankea sin juntar filas.
Los 2 mejores meses de cada sucursal
Ejemplo resuelto · 4 pasos
Con ventas_mensuales: para cada sucursal, sus 2 meses de 2025 con más ventas, con mes, ventas y su lugar.
Piensa el siguiente paso por tu cuenta y luego ábrelo para comparar.
Inténtalo
Contesta la pregunta de abajo y escribe tu consulta. Si te atoras en una de las cuatro decisiones, cuéntale a tu Maestro cuál.
Comprueba lo que sabes: En febrero, Café de olla y Concha vendieron 134 unidades cada uno, empatados en el tercer lugar. Si usas ROW_NUMBER() OVER (PARTITION BY mes ORDER BY unidades DESC, producto) y QUALIFY ... <= 3, ¿qué pasa en febrero?
Tu turno
Regresa mes, producto, unidades y lugar (el lugar del producto en su mes, de más a menos unidades) solo para los productos en los lugares 1 a 3 de cada mes. Usa puestos de competencia: los empatados comparten lugar y los puestos siguientes dejan huecos. Entran todos los productos cuyo lugar sea 1, 2 o 3. Ordena por mes, lugar, producto. Terminaste cuando ves 3 productos por mes, salvo uno con un empate.
Tablas: ventas_productos (mes, producto, unidades)
ventas_productos · 24 filas
| Columna | Tipo |
|---|---|
| mes Primer día del mes. | DATE |
| producto Nombre del producto. | VARCHAR |
| unidades Unidades vendidas en el mes. | BIGINT |
Primeras filas
| mes | producto | unidades |
|---|---|---|
| 2025-01-01 | Café de olla | 56 |
| 2025-01-01 | Concha | 128 |
| 2025-01-01 | Tamal | 149 |
Tab agrega sangría; Esc y Tab para salir
Si elegiste RANK, febrero tiene 4 productos: Café de olla y Concha vendieron 134 unidades cada uno y comparten el tercer lugar. Así se ve febrero con las tres funciones, en una corrida en el sandbox (ROW_NUMBER desempatado por producto):
| producto | unidades | ROW_NUMBER | RANK | DENSE_RANK |
|---|---|---|---|---|
| Chilaquiles | 155 | 1 | 1 | 1 |
| Pan de elote | 151 | 2 | 2 | 2 |
| Café de olla | 134 | 3 | 3 | 3 |
| Concha | 134 | 4 | 3 | 3 |
| Atole | 98 | 5 | 5 | 4 |
| Tamal | 46 | 6 | 6 | 5 |
Con ROW_NUMBER desempatado por producto, Concha quedaría fuera por la regla alfabética, no por haber vendido menos. Aquí DENSE_RANK con <= 3 da el mismo resultado que RANK, porque el empate está justo en el corte. Pero responden políticas distintas. Con ventas 200, 200, 150 y 140, RANK asigna 1, 1, 3, 4: el filtro <= 3 conserva tres productos. DENSE_RANK asigna 1, 1, 2, 3 y conserva los cuatro, porque selecciona los tres niveles de venta distintos. El reto pide la primera política; si el negocio quisiera tres niveles distintos, cambiaría la elección.
Es de las preguntas de entrevista más comunes: "los 3 productos más vendidos de cada categoría", "los 2 empleados mejor pagados de cada departamento" o "el top 5 de canciones por país". Antes de escribir, pregunta qué pasa con un empate: esa pregunta, dicha en voz alta, ya es la mitad de la respuesta que buscan. Si quieres ensayarla, pídele a tu Maestro que te haga una versión con otros datos.
Tu tarea para esta semana: busca un reporte que diga "top" o "los principales" y revisa cómo corta. Si usa LIMIT sobre un resultado con varios grupos, o ROW_NUMBER sin que nadie haya decidido qué pasa con un empate, ya sabes qué preguntar.
¿Qué tanto cambió lo que sabes?
En la primera página contestaste cinco preguntas antes de empezar. Aquí están otra vez, con otras palabras y otros datos.
Comprueba lo que sabes, 1 de 5: Una tabla tiene 24 filas de 4 meses. Agregas AVG(unidades) OVER (PARTITION BY mes) al SELECT, sin GROUP BY. ¿Cuántas filas regresa?
Comprueba lo que sabes, 2 de 5: Calculaste lugar con RANK() OVER (PARTITION BY mes ORDER BY unidades DESC) AS lugar. ¿Dónde puedes escribir la condición lugar <= 3?
Cuatro productos venden 200, 200, 150 y 140 unidades. Escribe sus puestos con RANK y DENSERANK. ¿Cuántos productos conserva lugar <= 3 con cada función? Si te piden los tres niveles de venta distintos, ¿cuál eliges y por qué?
Comprueba lo que sabes, 3 de 5: Cuatro productos venden 200, 200, 150 y 140 unidades. Escribe sus puestos con RANK y DENSE_RANK. ¿Cuántos productos conserva lugar <= 3 con cada función? Si te piden los tres niveles de venta distintos, ¿cuál eliges y por qué?
Comprueba lo que sabes, 4 de 5: Haces un acumulado con SUM(unidades) OVER (ORDER BY mes) y hay seis filas por mes. ¿Qué muestran las seis filas de enero?
Comprueba lo que sabes, 5 de 5: Un cliente compró en enero, febrero y abril, pero no en marzo. Con LAG(fecha) OVER (ORDER BY fecha), ¿qué sale en la fila de abril?
Piensa en una consulta o un reporte de tu trabajo. ¿Dónde usarías primero una de estas ventanas, y qué trampa de este curso (empates, un mes que falta, el marco por omisión o el WHERE antes de la ventana) tendrías que revisar antes de confiar en el resultado?
Reflexiona: Piensa en una consulta o un reporte de tu trabajo. ¿Dónde usarías primero una de estas ventanas, y qué trampa de este curso (empates, un mes que falta, el marco por omisión o el WHERE antes de la ventana) tendrías que revisar antes de confiar en el resultado?
Solo tú y tu Maestro leen esto. Se queda en tu cuenta y se borra con ella.
Lo que sigue
Ya puedes poner el total de un grupo junto a cada fila, numerar y quedarte con una fila por grupo, comparar con la fila anterior sabiendo que LAG cuenta filas y no meses, acumular y suavizar eligiendo tu marco, y decir en qué momento corre cada pieza. Con eso resuelves la mayoría de las consultas con ventanas que vas a ver en reportes y en entrevistas.
El mejor siguiente paso es llevar una de estas consultas a tus datos del trabajo, con tu Maestro al lado. Este curso no enseña uniones ni cómo crear datos: si en el camino sentiste flojo GROUP BY, las uniones o los WITH, el curso SQL para gente de datos los trabaja a fondo, desde qué es una base de datos.