La solicitud

De Megan Collins, Directora de Ventas
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 todos los meses. Devuelve solo los 12 meses de 2025 con: month (primer día, como DATE), net_revenue (redondeado a 2), prev_revenue (los ingresos netos del mes calendario anterior, redondeados a 2; para enero de 2025 es diciembre de 2024) y mom_growth_pct ((net_revenue - prev_revenue) / prev_revenue * 100, redondeado a 1). Ordena por month ascendente.
- Lee de la tabla
orderspendiente - Lee de la tabla
order_itemspendiente - Muestra exactamente
monthnet_revenueprev_revenuemom_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 Megan, 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
LAG(x) devuelve el valor de x de la fila anterior en el orden de la ventana. LEAD(x) devuelve el
de la fila siguiente. Hacen trivial comparar un periodo con el anterior:
SELECT
month,
net_revenue,
LAG(net_revenue) OVER (ORDER BY month) AS prev_revenue
FROM monthly;
El crecimiento es entonces simple aritmética: (net_revenue - prev_revenue) / prev_revenue * 100.
Filtra después de la ventana, no antes
Esta es la trampa en la petición de Megan. Si la CTE monthly solo contuviera 2025, enero no tendría fila
anterior y prev_revenue sería NULL. Las funciones de ventana solo ven las filas que sobreviven al WHERE.
Entonces:
- Construye los ingresos mensuales de todos los meses.
- Calcula LAG sobre todos ellos.
- Filtra a 2025 en la consulta externa.
Enero de 2025 se compara entonces correctamente con diciembre de 2024. El mismo principio se aplica a los totales acumulados, las medias móviles y los rankings: filtrar pronto cambia lo que ve la ventana.
Opciones de LAG
LAG(net_revenue, 12) OVER (ORDER BY month) -- same month last year (year-over-year)
LAG(net_revenue, 1, 0) OVER (ORDER BY month) -- default 0 instead of NULL
LEAD(net_revenue) OVER (ORDER BY month) -- next month
LAG(x, 12) para año a año solo funciona si todos los meses están presentes. LAG cuenta filas, no
meses calendario: si falta un mes, “12 filas atrás” son 13 meses atrás. Con datos dispersos, haz primero
un join con un calendario generado (capítulo 6), o une cada mes con month - INTERVAL 1 YEAR.
Evita el valor por defecto 0 en los cálculos de crecimiento. Dividir entre un cero falso es un error o
infinito, y un crecimiento NULL en el primer periodo es la respuesta honesta.
Por grupo
Añade PARTITION BY para comparar dentro de cada grupo, por ejemplo los días desde el pedido anterior de
cada cliente:
CAST(order_date AS DATE)
- LAG(CAST(order_date AS DATE)) OVER (PARTITION BY customer_id ORDER BY order_date) AS days_since_prev
Estacionalidad
El crecimiento mes a mes es ruidoso en un negocio estacional. Harbor & Pine vende mucho más en noviembre y diciembre, así que enero siempre parece un desplome junto a diciembre. Por eso los equipos de finanzas suelen preferir el crecimiento año a año del mismo mes, que compara cosas equivalentes.
Porcentaje vs puntos porcentuales
Si la tasa de conversión pasa de 2.0% a 2.5%, eso son +0.5 puntos porcentuales, o +25% de crecimiento relativo. Di cuál de los dos quieres decir en un informe; la gente los confunde constantemente.
Nota de entrevista
“Calcula el crecimiento mes a mes” es una pregunta estándar de entrevista de analista. Las buenas respuestas agregan a meses en una CTE, usan LAG, explican qué pasa con el primer mes y mencionan que LAG cuenta filas, así que los meses faltantes necesitan un calendario.
Errores comunes
- Filtrar a 2025 antes del LAG. Enero se queda entonces sin fila anterior y su crecimiento es NULL. Calcula LAG sobre todos los meses y luego filtra en la consulta externa.
- Dividir entre el mes equivocado. El crecimiento es
(net_revenue - prev_revenue) / prev_revenue, no/ net_revenue. - Darle a LAG un valor por defecto de 0.
LAG(net_revenue, 1, 0)hace que el primer mes divida entre cero. Deja el valor por defecto en NULL. - Usar
LAG(x, 12)para año a año cuando faltan meses. LAG cuenta filas, no meses calendario, así que un hueco desplaza todas las comparaciones posteriores.
En SQL Server
LAG(net_revenue, 1) OVER (ORDER BY month) es idéntico. Protege la tasa de crecimiento con
NULLIF(prev_revenue, 0), que SQL Server también tiene, y recuerda que dividir dos enteros trunca.
¡Linterna encendida!
Practicaste: lagleadmom growthwindow functionscte
- Resuelto
- Sin pistas
- Al primer intento
