La solicitud

De Catherine Hale, Directora Ejecutiva
Tu objetivo
Paso 1 de 3. Para los pedidos completados realizados en 2025, devuelve una fila por categoría con: category, net_revenue (redondeado a 2) y pct_of_total (la participación de la categoría en los ingresos netos totales de 2025 sumando todas las categorías, por 100, redondeada a 1). Ordena por net_revenue descendente.
- Lee de la tabla
productspendiente - Lee de la tabla
orderspendiente - Muestra exactamente
categorynet_revenuepct_of_totalpendiente
Paso 2 de 3. Numera los pedidos completados de cada cliente por order_date (desempata por order_id). Para los clientes que tienen un segundo pedido completado, devuelve una fila por segment (de customers) con: segment, customers (número de clientes con un segundo pedido) y avg_days_to_second (promedio de días entre las fechas calendario del primer y el segundo pedido completado, redondeado a 1).
- Lee de la tabla
customerspendiente - Lee de la tabla
orderspendiente - Muestra exactamente
segmentcustomersavg_days_to_secondpendiente
Paso 3 de 3. Asigna cada cliente al mes de su primer pedido completado (cohort_month, un DATE). Para las cohortes de enero a junio de 2025, devuelve: cohort_month, cohort_size (clientes de la cohorte), retained_m1 (clientes de la cohorte con al menos un pedido completado en el mes calendario inmediatamente posterior al mes de la cohorte) y retention_m1_pct (retained_m1 / cohort_size * 100, redondeado a 1). Ordena por cohort_month ascendente.
- Lee de la tabla
orderspendiente - Muestra exactamente
cohort_monthcohort_sizeretained_m1retention_m1_pctpendiente - 6 filas, ordenadas como se pidependiente
Paso 1 · tu consulta
Cargando el editor…
Solución de referencia
| product_id | name | category | subcategory | unit_price |
|---|---|---|---|---|
| 101 | Vale Velvet Loveseat | Furniture | Sofas | 1659.00 |
| 102 | Alder Oak Coffee Table | Furniture | Tables | 919.00 |
| 103 | Orchard Rattan Dining Chair | Furniture | Chairs | 789.00 |
| 104 | Upland Oak Bookcase | Furniture | Storage | 429.00 |
Mote revisa tu resultado
Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.
Paso 2 · tu consulta
Cargando el editor…
Solución de referencia
| customer_id | first_name | last_name | city | |
|---|---|---|---|---|
| 1 | Owen | Hudson | owen.hudson@icloud.com | San Francisco |
| 2 | Douglas | Mendoza | dmendoza69@gmail.com | Atlanta |
| 3 | Henry | Brooks | hbrooks@lakesidecafe.com | Los Angeles |
| 4 | Brian | Graham | bgraham@bluecedarhomes.com | Seattle |
Mote revisa tu resultado
Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.
Paso 3 · 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 Catherine, y por qué
Tablas
Datos de la tienda Harbor & Pine, listos para consultar.
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 |
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 |
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
El análisis de cohortes es la prueba clásica para llevar a casa de los analistas: necesita CTE, funciones de ventana, lógica de fechas y una definición clara, todo a la vez. Este desafío final te lleva hasta ahí paso a paso.
Paso 1: participación sobre el total
Agrega por categoría y luego divide cada fila entre el total general:
ROUND(100.0 * net_revenue / SUM(net_revenue) OVER (), 1) AS pct_of_total
Un OVER () vacío hace que la ventana sea todo el resultado, así que cada fila ve el mismo total. Sin
subconsulta, sin join. Las participaciones deben sumar cerca de 100; si suman mucho más, un join multiplicó
filas.
Paso 2: tiempo hasta el segundo pedido
ROW_NUMBER numera los pedidos de cada cliente en orden cronológico. LAG da entonces el intervalo de
cada pedido respecto al anterior, y conservar order_number = 2 deja exactamente una fila por cliente
que vuelve: el intervalo entre su primer y su segundo pedido. El desempate por order_id protege contra
dos pedidos con la misma marca de tiempo.
El starter muestra los pedidos numerados de un solo cliente. Inspeccionar una sola entidad así es como se comprueba que una ventana tiene sentido antes de agregarla.
Los clientes que nunca hicieron un segundo pedido no entran en el promedio. Eso es correcto para “cuánto tardan en volver”, pero preséntalo junto a cuántos no volvieron nunca, o el número se ve mejor que la realidad.
Paso 3: retención por cohortes
Tres definiciones forman una tabla de cohortes:
- Cohorte: el mes del primer pedido completado de un cliente.
MIN(order_month) OVER (PARTITION BY customer_id)la adjunta a cada una de sus filas sin colapsarlas. - Actividad: un cliente está activo en un mes si hizo al menos un pedido completado. La CTE
customer_monthsusaSELECT DISTINCTa propósito, para obtener una fila por cliente por mes, el grano correcto para “activo o no”. - Retenido en el mes 1: activo en el mes calendario inmediatamente posterior al mes de la cohorte.
COUNT(DISTINCT CASE WHEN order_month = CAST(cohort_month + INTERVAL '1 month' AS DATE)
THEN customer_id END) AS retained_m1
COUNT(DISTINCT CASE ...) cuenta los clientes que cumplen la condición. El CASE devuelve NULL en los demás
casos, y COUNT ignora los NULL.
El filtro de cohortes se aplica después de la ventana, en la consulta externa. Filtrar los pedidos a 2025 antes de calcular el MIN asignaría a una cohorte de 2025 a los clientes que compraron por primera vez en 2024, la misma trampa que con LAG y las medias móviles.
Notas de dialecto
Sumar un mes: DuckDB y Postgres aceptan date + INTERVAL '1 month' (el resultado es un timestamp, de ahí
el cast). BigQuery usa DATE_ADD(cohort_month, INTERVAL 1 MONTH), MySQL
DATE_ADD(cohort_month, INTERVAL 1 MONTH), Snowflake DATEADD(month, 1, cohort_month).
Ir más allá
La tabla de cohortes completa tiene una columna para cada desfase de mes (m1, m2, m3, …), que suele
calcularse con DATEDIFF en meses entre order_month y cohort_month, agrupando por cohorte y desfase y
luego pivotando. En una entrevista, acertar el mes 1, con definiciones claras dichas en voz alta, vale más
que una cuadrícula completa hecha a toda prisa.
Errores comunes
- Filtrar los pedidos a 2025 antes del MIN. Los clientes que compraron por primera vez en 2024 quedan entonces en una cohorte de 2025. Calcula el mes de la cohorte sobre todos los pedidos y filtra por fuera.
- Contar filas en lugar de clientes.
COUNT(*)sobre filas de pedidos cuenta pedidos, no clientes activos. UsaCOUNT(DISTINCT customer_id), o una CTE de una fila por cliente por mes. - Reportar solo el intervalo promedio hasta un segundo pedido. Cubre únicamente a los clientes que volvieron; muestra a su lado cuántos nunca hicieron un segundo pedido.
- Numerar pedidos sin un criterio de desempate. Dos pedidos con la misma marca de tiempo pueden intercambiar
el primer y el segundo puesto. Añade
order_idal ORDER BY del ROW_NUMBER.
En SQL Server
Suma un mes con DATEADD(month, 1, cohort_month); DATEDIFF(month, cohort_month, order_month) da el
desfase de mes para una cuadrícula completa de cohortes. Los intervalos en días necesitan
DATEDIFF(day, prev_day, order_day), porque - entre fechas da error. Las funciones de ventana en sí no
cambian.
¡Linterna encendida!
Practicaste: window functionsrow numberlagsum overcohort retentioncte
- Resuelto
- Sin pistas
- Al primer intento
