1. Faro

Nivel 8 · Desafío final: la revisión anual del negocio

La solicitud

De Catherine Hale, Directora Ejecutiva

“Para la revisión anual de 2025 quiero tres diapositivas: cómo creció cada canal de venta frente a 2024, los dos mejores productos por categoría en el Q4 y qué parte de los ingresos de cada trimestre vino de clientes que repiten.”

Tu objetivo

Paso 1 de 3. Devuelve una fila por canal con: channel, revenue_2024 (ingresos netos de los pedidos realizados en 2024, redondeados a 2), revenue_2025 (lo mismo para 2025, redondeado a 2), yoy_growth_pct ((revenue_2025 - revenue_2024) / revenue_2024 * 100, redondeado a 1) y share_2025_pct (la participación del canal en los ingresos netos totales de 2025 sumando todos los canales, por 100, redondeada a 1). Ordena por revenue_2025 descendente.

  • Lee de la tabla orderspendiente
  • Lee de la tabla order_itemspendiente
  • Muestra exactamente channel revenue_2024 revenue_2025 yoy_growth_pct share_2025_pctpendiente

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 products · presiona Ejecutar para ver el tuyo
      Vista previa de products
      product_idnamecategorysubcategoryunit_price
      101Vale Velvet LoveseatFurnitureSofas1659.00
      102Alder Oak Coffee TableFurnitureTables919.00
      103Orchard Rattan Dining ChairFurnitureChairs789.00
      104Upland Oak BookcaseFurnitureStorage429.00

      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
        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
        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
        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
        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

        Una revisión anual del negocio es un puñado de patrones de análisis puestos lado a lado. Este desafío final pide tres de ellos, y cada uno tiene una decisión que lo hace acertado o equivocado.

        Paso 1: crecimiento y participación por canal

        Pon ambos años en la misma fila con agregación condicional, de modo que el crecimiento sea una simple expresión de columnas:

        SUM(CASE WHEN o.order_date >= '2024-01-01' AND o.order_date < '2025-01-01'
                 THEN i.quantity * i.unit_price * (1 - i.discount_pct / 100.0) END) AS revenue_2024

        La participación de 2025 necesita el total general en cada fila: SUM(revenue_2025) OVER (). La respuesta es una diapositiva llamativa: la app creció un 53.2% y ahora es el canal más grande (43.3% de los ingresos de 2025), mientras que la web se encogió un 7.2%. El crecimiento total habría ocultado ese cambio.

        Paso 2: dos productos por categoría

        Aquí el encargo dice exactamente dos por categoría, así que ROW_NUMBER() con un desempate por product_id es la función correcta, a diferencia del ranking con empates incluidos de antes en el capítulo. Atento a los casos reñidos: en Textiles la Bramble Percale Quilt superó a la Delancey Cashmere-Blend Duvet Cover por menos de $50 en el Q4 de 2025, y en Decor los dos primeros están a $94 de distancia. En una diapositiva, un margen tan estrecho merece una nota al pie.

        Paso 3: ingresos de primer pedido vs recompra

        “¿El negocio se sostiene en clientes que repiten?” Numera los pedidos completados de cada cliente sobre todo el historial y luego mira 2025:

        ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date, order_id) AS order_number

        Un pedido con order_number = 1 es el primero de ese cliente de todos los tiempos. Todo lo demás son ingresos de recompra. En Harbor & Pine, entre el 86% y el 91% de los ingresos de cada trimestre de 2025 vino de pedidos repetidos. Es la firma de una base de clientes madura: la mayoría de los clientes hicieron su primer pedido antes de 2025.

        El orden de las operaciones es todo el sentido. Primero numera, después filtra. Si filtras los pedidos a 2025 dentro de la CTE, un cliente que compró por primera vez en 2023 obtiene order_number = 1 en su primer pedido de 2025, y los ingresos de recompra quedan muy subestimados.

        Errores comunes

        • Dos consultas separadas para 2024 y 2025 unidas después: más código, más sitios donde los filtros pueden diferir.
        • LIMIT para el top N por grupo. Limita el resultado completo, no cada categoría.
        • Filtrar antes de numerar en el paso 3.

        En SQL Server

        Las sumas con CASE funcionan sin cambios; SUM(...) OVER () y ROW_NUMBER() también. Sustituye DATE_TRUNC('quarter', order_date) por DATETRUNC(quarter, order_date) (2022+) o por DATEFROMPARTS(YEAR(order_date), (DATEPART(quarter, order_date) - 1) * 3 + 1, 1). Para conservar solo los 2 primeros sin QUALIFY, filtra la CTE clasificada en la consulta externa, como aquí.

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