1. Faro

Nivel 2 · Revisa y compara la subida de precios en SQL

La solicitud

De Thomas Whitaker, Director de Merchandising

“Acordamos la pregunta: para los productos cuyo precio subió el 1 de marzo, unidades e ingresos de marzo a agosto frente a los mismos meses del año pasado, junto a los productos que dejamos como estaban. Primero muéstrame que encontraste los productos correctos y que el cambio de verdad ocurrió el 1 de marzo.”

Tu objetivo

Paso 1 de 2. Revisa el cambio. Para cada línea de pedido de los productos cuyo precio subió, etiqueta period ('before' si order_date < '2025-03-01', si no 'after') y price_paid ('old' si el unit_price de la línea es igual al precio más bajo del producto, si no 'new'). Devuelve period, price_paid y lines (el número de líneas de pedido), ordenado por period de forma descendente y luego por price_paid de forma descendente. Usa todas las líneas de pedido, sea cual sea el estado.

  • Lee de la tabla orderspendiente
  • Lee de la tabla order_itemspendiente
  • Muestra exactamente period price_paid linespendiente

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.

      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

      Qué estás revisando, y por qué

      Antes de comparar nada, demuestra que estás mirando los productos correctos y la fecha correcta. Thomas dice «unos 30 productos, 1 de marzo». Los datos pueden confirmar ambas cosas, porque order_items guarda el precio pagado en cada línea, mientras que products.unit_price solo guarda el precio de lista de hoy.

      Un producto cuyo precio cambió tiene dos precios distintos entre sus líneas de pedido. Eso es una condición sobre grupos, así que va en HAVING:

      SELECT product_id, MIN(unit_price) AS old_price, MAX(unit_price) AS new_price
      FROM order_items
      GROUP BY product_id
      HAVING MIN(unit_price) <> MAX(unit_price);

      Esto devuelve 29 productos. La revisión del paso 1 etiqueta entonces cada una de sus líneas dos veces, por fecha y por precio, y cuenta las combinaciones. Si el cambio ocurrió limpiamente el 1 de marzo, solo existen dos combinaciones: antes con el precio viejo, después con el nuevo. Cualquier otra fila es un hallazgo en sí misma.

      En igualdad de condiciones, con un grupo de control

      El paso 2 responde la pregunta acordada. Tres decisiones hacen justa la comparación:

      • Los mismos meses, con un año de diferencia. De marzo a agosto de 2025 frente a marzo a agosto de 2024. La temporada es la misma en ambos lados.
      • Productos en igualdad de condiciones. Solo los productos lanzados antes del 1 de enero de 2024, para que todos estuvieran a la venta durante ambas ventanas completas.
      • Un grupo de control. Todos los demás productos se etiquetan como unchanged. Su crecimiento es la línea base: lo que la tienda hizo de todos modos.

      El patrón para dos periodos lado a lado es la agregación condicional, el mismo que se usa en los informes año contra año:

      SUM(CASE WHEN yr = 2024 THEN quantity END) AS u24,
      SUM(CASE WHEN yr = 2025 THEN quantity END) AS u25

      Guarda estas sumas en bruto en una CTE y calcula el porcentaje en el SELECT final, para que se calcule con números sin redondear.

      Cómo leer el resultado

      price_group units_change_pct revenue_change_pct
      raised 21.0 44.3
      unchanged 9.2 13.4

      Si la subida hubiera dañado la demanda, los productos con precio más alto crecerían menos que los que no cambiaron. Crecieron más. Los ingresos crecieron más rápido que las unidades en los productos con precio más alto porque cada unidad dejó cerca de 6% más y porque las ventas se desplazaron hacia los artículos más caros del grupo.

      Errores comunes

      • BETWEEN '2025-03-01' AND '2025-08-31' sobre una marca de tiempo deja fuera la noche del 31 de agosto; usa un rango semiabierto.
      • Contar pedidos cancelled o refunded suma ventas que nunca ocurrieron.
      • IN (SELECT ...) está bien para 29 ids; con millones de filas, un JOIN con la CTE es el hábito más rápido.

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