1. Faro

Nivel 11 · Desafío final: primeros pedidos y recompras

La solicitud

De Megan Collins, Directora de Ventas

“El CEO preguntó si se nos da bien hacer volver a los clientes. Quiero la fecha del primer pedido completado de cada cliente, el número de clientes nuevos que captamos cada mes de 2025 y la proporción de los clientes nuevos de 2024 que volvieron a pedir en 90 días.”

Tu objetivo

Paso 1 de 3. Devuelve customer_id y first_order_date (la parte de fecha, como DATE, de su pedido completado más temprano) de todo cliente con al menos un pedido completado.

  • Lee de la tabla orderspendiente
  • Muestra exactamente customer_id first_order_datependiente
  • 1,730 filaspendiente

Paso 1 · tu consulta

SQL

Cargando el editor…

    ResultadoVista previa de orders · presiona Ejecutar para ver el tuyo
    Vista previa de orders
    order_idcustomer_idorder_datestatuschannel
    10011252023-01-01 20:51:19completedweb
    10021562023-01-02 07:58:46completedweb
    1003222023-01-02 10:25:27completedmarketplace
    1004482023-01-02 11:21:51completedmarketplace

    Mote revisa tu resultado

    Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.

    Paso 2 · tu consulta

    SQL

    Cargando el editor…

      ResultadoVista previa de orders · presiona Ejecutar para ver el tuyo
      Vista previa de orders
      order_idcustomer_idorder_datestatuschannel
      10011252023-01-01 20:51:19completedweb
      10021562023-01-02 07:58:46completedweb
      1003222023-01-02 10:25:27completedmarketplace
      1004482023-01-02 11:21:51completedmarketplace

      Mote revisa tu resultado

      Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.

      Paso 3 · tu consulta

      SQL

      Cargando el editor…

        ResultadoVista previa de orders · presiona Ejecutar para ver el tuyo
        Vista previa de orders
        order_idcustomer_idorder_datestatuschannel
        10011252023-01-01 20:51:19completedweb
        10021562023-01-02 07:58:46completedweb
        1003222023-01-02 10:25:27completedmarketplace
        1004482023-01-02 11:21:51completedmarketplace

        Mote revisa tu resultado

        Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.

        Tablas

        Datos de la tienda Harbor & Pine, listos para consultar.

        orders12,000 filas · 7 columnas
        • order_idinteger
        • customer_idinteger
        • order_datetimestamp
        • statusvarchar
        • channelvarchar
        • shipping_feedecimal
        • coupon_codevarchar
        Primeras 5 filas de orders
        order_idcustomer_idorder_datestatuschannelshipping_feecoupon_code
        10011252023-01-01 20:51:19completedweb0.00NULL
        10021562023-01-02 07:58:46completedweb0.00NULL
        1003222023-01-02 10:25:27completedmarketplace4.99WELCOME10
        1004482023-01-02 11:21:51completedmarketplace4.99WELCOME10
        1005822023-01-02 11:43:36completedweb0.00WELCOME10
        customers2,018 filas · 9 columnas
        • customer_idinteger
        • first_namevarchar
        • last_namevarchar
        • emailvarchar
        • cityvarchar
        • statevarchar
        • signup_datedate
        • segmentvarchar
        • referral_sourcevarchar
        Primeras 5 filas de customers
        customer_idfirst_namelast_nameemailcitystatesignup_datesegmentreferral_source
        1OwenHudsonowen.hudson@icloud.comSan FranciscoCA2022-06-02consumersearch
        2DouglasMendozadmendoza69@gmail.comAtlantaGA2022-06-02consumerNULL
        3HenryBrookshbrooks@lakesidecafe.comLos AngelesCA2022-06-04businessNULL
        4BrianGrahambgraham@bluecedarhomes.comSeattleWA2022-06-06businesspinterest
        5KyleJimenezkjimenez27@yahoo.comIndianapolisIN2022-06-07consumerNULL
        products120 filas · 8 columnas
        • product_idinteger
        • namevarchar
        • categoryvarchar
        • subcategoryvarchar
        • unit_pricedecimal
        • unit_costdecimal
        • launched_ondate
        • is_activeboolean
        Primeras 5 filas de products
        product_idnamecategorysubcategoryunit_priceunit_costlaunched_onis_active
        101Vale Velvet LoveseatFurnitureSofas1659.00NULL2023-09-11true
        102Alder Oak Coffee TableFurnitureTables919.00503.502024-05-16true
        103Orchard Rattan Dining ChairFurnitureChairs789.00429.872023-05-27true
        104Upland Oak BookcaseFurnitureStorage429.00214.702022-12-20true
        105Avery Leather Bed FrameFurnitureBeds449.00232.702021-08-31true
        order_items30,338 filas · 6 columnas
        • order_item_idinteger
        • order_idinteger
        • product_idinteger
        • quantityinteger
        • unit_pricedecimal
        • discount_pctdecimal
        Primeras 5 filas de order_items
        order_item_idorder_idproduct_idquantityunit_pricediscount_pct
        11001121931.990.00
        21001154311.990.00
        31002154411.990.00
        410021941149.000.00
        51002193219.990.00
        returns1,673 filas · 5 columnas
        • return_idinteger
        • order_item_idinteger
        • returned_ondate
        • reasonvarchar
        • refund_amountdecimal
        Primeras 5 filas de returns
        return_idorder_item_idreturned_onreasonrefund_amount
        1142023-01-10damaged83.69
        2422023-01-10wrong_item19.99
        31052023-01-14wrong_item10.99
        4242023-01-16changed_mind26.99
        51262023-01-16late20.99
        employees60 filas · 8 columnas
        • employee_idinteger
        • first_namevarchar
        • last_namevarchar
        • departmentvarchar
        • titlevarchar
        • manager_idinteger
        • hire_datedate
        • salaryinteger
        Primeras 5 filas de employees
        employee_idfirst_namelast_namedepartmenttitlemanager_idhire_datesalary
        1CatherineHaleExecutiveChief Executive OfficerNULL2016-03-01285000
        2RobertKimExecutiveChief Operating Officer12017-01-09235000
        3MeganCollinsSalesHead of Sales12018-04-16172000
        4ChloeGutierrezSalesAccount Executive32020-01-2172000
        5FrankBellSalesAccount Executive32023-05-2173000
        web_sessions40,000 filas · 7 columnas
        • session_idinteger
        • customer_idinteger
        • started_attimestamp
        • devicevarchar
        • sourcevarchar
        • pages_viewedinteger
        • convertedboolean
        Primeras 5 filas de web_sessions
        session_idcustomer_idstarted_atdevicesourcepages_viewedconverted
        1NULL2023-01-01 23:02:24mobilepaid1false
        2182023-01-01 15:07:49desktoppaid1false
        3NULL2023-01-01 16:55:46desktopdirect7false
        4NULL2023-01-01 12:43:28mobileorganic3false
        5NULL2023-01-01 13:06:21mobilesocial2false
        marketing_spend3,276 filas · 3 columnas
        • spend_datedate
        • channelvarchar
        • amountdecimal
        Primeras 5 filas de marketing_spend
        spend_datechannelamount
        2023-01-01paid492.99
        2023-01-01email37.38
        2023-01-01social200.53
        2023-01-02paid709.13
        2023-01-02email64.13

        La lección

        Las preguntas de retención empiezan todas igual: encuentra el primer evento de cada cliente y luego mira lo que pasa después. Los CTE están hechos para esto, porque cada paso tiene un grano claro.

        Paso 1: primer pedido por cliente

        SELECT customer_id, CAST(MIN(order_date) AS DATE) AS first_order_date
        FROM orders
        WHERE status = 'completed'
        GROUP BY customer_id;

        Una fila por cliente. Si un pedido cancelado cuenta como “captar” a un cliente es una definición de negocio. El ticket de Megan dice solo completados, así que el filtro va antes del MIN. Si lo pones después, un cliente cuyo primer pedido fue cancelado se captaría en la fecha equivocada.

        Paso 2: clientes nuevos por mes

        Con los primeros pedidos en un CTE, “clientes nuevos por mes” es un DATE_TRUNC y un conteo. El filtro de año se aplica a first_order_at, no a todos los pedidos: un cliente que compró por primera vez en 2023 y de nuevo en 2025 no es nuevo en 2025. Confundir esos dos filtros es uno de los errores más comunes en los informes de captación.

        Paso 3: tasa de recompra a 90 días

        Define la cohorte (primer pedido completado en 2024) y luego marca a cada miembro que volvió:

        CASE WHEN EXISTS (
          SELECT 1 FROM orders AS o
          WHERE o.customer_id = c.customer_id
            AND o.status = 'completed'
            AND o.order_date >  c.first_order_at
            AND o.order_date <= c.first_order_at + INTERVAL '90 days'
        ) THEN 1 ELSE 0 END AS repeated

        EXISTS busca al menos un pedido que califique, así que un cliente con cinco pedidos de recompra se cuenta una sola vez. Un JOIN aquí generaría fan-out e inflaría el numerador. El > estricto excluye el primer pedido en sí. La tasa es la suma de las banderas sobre el tamaño de la cohorte.

        Usar una ventana fija (90 días desde el primer pedido de cada cliente) es deliberado. “Volvió a pedir en 2024” daría a los clientes de diciembre casi nada de tiempo para volver y a los de enero un año entero, lo que hace que la tasa dependa de cuándo se unió la gente y no de lo leal que es.

        INTERVAL '90 days' funciona en DuckDB y Postgres. MySQL y BigQuery escriben INTERVAL 90 DAY (BigQuery dentro de TIMESTAMP_ADD).

        Convertirlo en una historia

        Una sola tasa de recompra es útil; una tendencia es mejor. Agrupa el paso 3 por el mes del primer pedido y tendrás una tabla de cohortes: ¿los clientes captados en primavera volvieron más que los de la temporada navideña? Ese es el Desafío final del próximo capítulo, construido con funciones de ventana.

        Errores comunes

        • Filtrar el estado después de tomar el MIN. Si los pedidos cancelados siguen dentro cuando se ejecuta MIN(order_date), un cliente cuyo primer pedido fue cancelado obtiene la fecha de primera compra equivocada. Pon WHERE status = 'completed' en la misma consulta que el MIN.
        • Filtrar el año sobre todos los pedidos. WHERE order_date >= '2025-01-01' antes del MIN hace que un cliente de 2023 parezca nuevo en 2025. Filtra por first_order_at una vez calculado.
        • Usar >= en la ventana de recompra. o.order_date >= c.first_order_at coincide con el propio primer pedido, así que todos los clientes cuentan como recompra. Usa >.
        • Unir con los pedidos de recompra en lugar de usar EXISTS. Un cliente con cinco pedidos de recompra se cuenta cinco veces en el numerador.

        En SQL Server

        Reemplaza c.first_order_at + INTERVAL '90 days' por DATEADD(day, 90, c.first_order_at). Los CTE y MIN(order_date) no cambian, y la clave de mes es DATETRUNC(month, first_order_at) (SQL Server 2022) o DATEFROMPARTS(YEAR(first_order_at), MONTH(first_order_at), 1).

        Elige qué puede ejecutarse en este sitio. Puedes cambiarlo cuando quieras desde "Configurar cookies", al pie de cada página.