La solicitud

De Robert Kim, Director de Operaciones
Tu objetivo
Usando pedidos completados y líneas con quantity > 0, calcula los ingresos netos mensuales (suma de quantity * unit_price * (1 - discount_pct / 100.0)) de cada mes de los datos. Devuelve los 12 meses de 2025 con: month (primer día, como DATE), net_revenue (redondeado a 2), mom_growth_pct ((net_revenue - net_revenue del mes anterior) / net_revenue del mes anterior * 100, redondeado a 1) y yoy_growth_pct ((net_revenue - net_revenue del mismo mes un año antes) / ese valor * 100, redondeado a 1). Ordena por month ascendente.
- Lee de la tabla
orderspendiente - Lee de la tabla
order_itemspendiente - Muestra exactamente
monthnet_revenuemom_growth_pctyoy_growth_pctpendiente
Tu consulta
Cargando el editor…
Solución de referencia
| order_id | customer_id | order_date | status | channel |
|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace |
Mote revisa tu resultado
Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.
Lo que recibe Robert, y por qué
Tablas
Datos de la tienda Harbor & Pine, listos para consultar.
orders12,000 filas · 7 columnas
order_idintegercustomer_idintegerorder_datetimestampstatusvarcharchannelvarcharshipping_feedecimalcoupon_codevarchar
| order_id | customer_id | order_date | status | channel | shipping_fee | coupon_code |
|---|---|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web | 0.00 | NULL |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web | 0.00 | NULL |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace | 4.99 | WELCOME10 |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace | 4.99 | WELCOME10 |
| 1005 | 82 | 2023-01-02 11:43:36 | completed | web | 0.00 | WELCOME10 |
order_items30,338 filas · 6 columnas
order_item_idintegerorder_idintegerproduct_idintegerquantityintegerunit_pricedecimaldiscount_pctdecimal
| order_item_id | order_id | product_id | quantity | unit_price | discount_pct |
|---|---|---|---|---|---|
| 1 | 1001 | 121 | 9 | 31.99 | 0.00 |
| 2 | 1001 | 154 | 3 | 11.99 | 0.00 |
| 3 | 1002 | 154 | 4 | 11.99 | 0.00 |
| 4 | 1002 | 194 | 1 | 149.00 | 0.00 |
| 5 | 1002 | 193 | 2 | 19.99 | 0.00 |
customers2,018 filas · 9 columnas
customer_idintegerfirst_namevarcharlast_namevarcharemailvarcharcityvarcharstatevarcharsignup_datedatesegmentvarcharreferral_sourcevarchar
| customer_id | first_name | last_name | city | state | signup_date | segment | referral_source | |
|---|---|---|---|---|---|---|---|---|
| 1 | Owen | Hudson | owen.hudson@icloud.com | San Francisco | CA | 2022-06-02 | consumer | search |
| 2 | Douglas | Mendoza | dmendoza69@gmail.com | Atlanta | GA | 2022-06-02 | consumer | NULL |
| 3 | Henry | Brooks | hbrooks@lakesidecafe.com | Los Angeles | CA | 2022-06-04 | business | NULL |
| 4 | Brian | Graham | bgraham@bluecedarhomes.com | Seattle | WA | 2022-06-06 | business | |
| 5 | Kyle | Jimenez | kjimenez27@yahoo.com | Indianapolis | IN | 2022-06-07 | consumer | NULL |
products120 filas · 8 columnas
product_idintegernamevarcharcategoryvarcharsubcategoryvarcharunit_pricedecimalunit_costdecimallaunched_ondateis_activeboolean
| product_id | name | category | subcategory | unit_price | unit_cost | launched_on | is_active |
|---|---|---|---|---|---|---|---|
| 101 | Vale Velvet Loveseat | Furniture | Sofas | 1659.00 | NULL | 2023-09-11 | true |
| 102 | Alder Oak Coffee Table | Furniture | Tables | 919.00 | 503.50 | 2024-05-16 | true |
| 103 | Orchard Rattan Dining Chair | Furniture | Chairs | 789.00 | 429.87 | 2023-05-27 | true |
| 104 | Upland Oak Bookcase | Furniture | Storage | 429.00 | 214.70 | 2022-12-20 | true |
| 105 | Avery Leather Bed Frame | Furniture | Beds | 449.00 | 232.70 | 2021-08-31 | true |
returns1,673 filas · 5 columnas
return_idintegerorder_item_idintegerreturned_ondatereasonvarcharrefund_amountdecimal
| return_id | order_item_id | returned_on | reason | refund_amount |
|---|---|---|---|---|
| 1 | 14 | 2023-01-10 | damaged | 83.69 |
| 2 | 42 | 2023-01-10 | wrong_item | 19.99 |
| 3 | 105 | 2023-01-14 | wrong_item | 10.99 |
| 4 | 24 | 2023-01-16 | changed_mind | 26.99 |
| 5 | 126 | 2023-01-16 | late | 20.99 |
employees60 filas · 8 columnas
employee_idintegerfirst_namevarcharlast_namevarchardepartmentvarchartitlevarcharmanager_idintegerhire_datedatesalaryinteger
| employee_id | first_name | last_name | department | title | manager_id | hire_date | salary |
|---|---|---|---|---|---|---|---|
| 1 | Catherine | Hale | Executive | Chief Executive Officer | NULL | 2016-03-01 | 285000 |
| 2 | Robert | Kim | Executive | Chief Operating Officer | 1 | 2017-01-09 | 235000 |
| 3 | Megan | Collins | Sales | Head of Sales | 1 | 2018-04-16 | 172000 |
| 4 | Chloe | Gutierrez | Sales | Account Executive | 3 | 2020-01-21 | 72000 |
| 5 | Frank | Bell | Sales | Account Executive | 3 | 2023-05-21 | 73000 |
web_sessions40,000 filas · 7 columnas
session_idintegercustomer_idintegerstarted_attimestampdevicevarcharsourcevarcharpages_viewedintegerconvertedboolean
| session_id | customer_id | started_at | device | source | pages_viewed | converted |
|---|---|---|---|---|---|---|
| 1 | NULL | 2023-01-01 23:02:24 | mobile | paid | 1 | false |
| 2 | 18 | 2023-01-01 15:07:49 | desktop | paid | 1 | false |
| 3 | NULL | 2023-01-01 16:55:46 | desktop | direct | 7 | false |
| 4 | NULL | 2023-01-01 12:43:28 | mobile | organic | 3 | false |
| 5 | NULL | 2023-01-01 13:06:21 | mobile | social | 2 | false |
marketing_spend3,276 filas · 3 columnas
spend_datedatechannelvarcharamountdecimal
| spend_date | channel | amount |
|---|---|---|
| 2023-01-01 | paid | 492.99 |
| 2023-01-01 | 37.38 | |
| 2023-01-01 | social | 200.53 |
| 2023-01-02 | paid | 709.13 |
| 2023-01-02 | 64.13 |
La lección
“¿Estamos creciendo?” tiene dos respuestas habituales, y en un negocio estacional a menudo no coinciden. El mes a mes (MoM) compara un mes con el anterior. El año a año (YoY) lo compara con el mismo mes de un año antes. Los buenos informes muestran ambos y saben en cuál confiar.
LAG con desfase
LAG(x) mira una fila atrás. LAG(x, n) mira n filas atrás. En una tabla mensual con una fila por mes
y sin huecos, 12 filas atrás es el mismo mes del año pasado:
LAG(net_revenue, 1) OVER (ORDER BY month) AS prev_month,
LAG(net_revenue, 12) OVER (ORDER BY month) AS same_month_last_year
El crecimiento es entonces (actual - anterior) / anterior * 100. Escribe 100.0 para que la
aritmética siga siendo decimal en cualquier base de datos.
Ejemplo resuelto: el “desplome” de enero
Con los ingresos completados, tres meses de 2025 cuentan la historia:
| month | net_revenue | mom_growth_pct | yoy_growth_pct |
|---|---|---|---|
| 2025-01-01 | 150,570.98 | -48.2 | 37.8 |
| 2025-09-01 | 143,826.50 | -21.6 | -5.3 |
| 2025-11-01 | 292,364.40 | 67.4 | -8.4 |
Enero “cayó a la mitad” solo porque diciembre es el pico navideño. Frente a enero de 2024 creció un 37.8%. Noviembre parece un triunfo en MoM (+67.4%, Black Friday), pero estuvo un 8.4% por debajo de noviembre de 2024. La columna YoY es la que elimina la estacionalidad: compara cosas equivalentes.
El YoY más seguro: join por la fecha
LAG(x, 12) se rompe sin avisar cuando falta un mes, porque “12 filas atrás” ya no es “12 meses atrás”.
Un autojoin por la fecha nunca se desvía:
SELECT cur.month, cur.net_revenue, prev.net_revenue AS last_year
FROM monthly AS cur
LEFT JOIN monthly AS prev
ON prev.month = cur.month - INTERVAL 1 YEAR;
En Harbor & Pine todos los meses tienen ventas, así que ambas formas dan los mismos números. Con datos dispersos (un producto nuevo, una región pequeña) prefiere el join, o construye primero un calendario completo.
Filtra después de la ventana
Calcula LAG sobre todos los meses y conserva 2025 en la consulta externa. Un WHERE sobre 2025 dentro de
la CTE se ejecuta antes que la ventana, así que enero no tiene diciembre y ningún mes tiene un año
anterior.
Errores comunes
- Reportar el MoM como cifra principal en un negocio estacional. Sobre todo mide el calendario.
- Dividir entre la base equivocada. El crecimiento divide entre el valor anterior, no el actual.
- Un último mes parcial. Si el mes actual no ha terminado, ambas comparaciones lo subestiman. El quiz más adelante en este capítulo trata justo de eso.
En SQL Server
LAG(net_revenue, 12) OVER (ORDER BY month) es idéntico. Para la forma con join, usa
DATEADD(year, -1, cur.month). Ojo con las columnas enteras: 100 * (a - b) / b trunca cuando todos los
valores son enteros, así que conserva el 100.0.
LEFT JOIN monthly AS prev ON prev.month = DATEADD(year, -1, cur.month) ¡Linterna encendida!
Practicaste: yoy growthmom growthlagseasonalitycte
- Resuelto
- Sin pistas
- Al primer intento
