1. Faro

Nivel 2 · Verifica y compara pedidos con cupón en SQL

La solicitud

De Laura Bennett, Directora de Finanzas

“Acordamos la pregunta: cuánto nos costó cada cupón, cuánto valían sus pedidos y cómo se comparan con los pedidos de los mismos días sin código. Antes de todo eso, muéstrame que los descuentos de las líneas de pedido realmente coinciden con los códigos. No quiero construir un presupuesto sobre una columna rota.”

Tu objetivo

Paso 1 de 3. Verifica los descuentos. Une order_items con orders y etiqueta cada línea con coupon = COALESCE(o.coupon_code, 'none'). Devuelve coupon, orders (ids de pedido distintos), lines, min_discount y max_discount (el discount_pct más pequeño y más grande), ordenado por coupon. Usa todos los pedidos, sea cual sea su estado.

  • Lee de la tabla orderspendiente
  • Lee de la tabla order_itemspendiente
  • Muestra exactamente coupon orders lines min_discount max_discountpendiente

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
        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
        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
        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 verificando y por qué

        El cupón vive en dos lugares: el código en orders.coupon_code y el descuento en cada línea de order_items.discount_pct. Todos los números de este caso se construyen a partir del segundo, así que primero demuestra que concuerda con el primero. Una consulta agrupada lo hace:

        SELECT COALESCE(o.coupon_code, 'none') AS coupon,
               MIN(i.discount_pct) AS min_discount,
               MAX(i.discount_pct) AS max_discount
        FROM order_items AS i
        JOIN orders AS o ON o.order_id = i.order_id
        GROUP BY coupon;

        Si el mínimo y el máximo de un código son iguales, todas sus líneas llevan el mismo descuento. Otras tres cosas que buscar en el mismo resultado: un código escrito de dos maneras (welcome10 junto a WELCOME10), pedidos sin código que aun así llevan descuento, y cuántos pedidos no tienen ningún código. COALESCE importa aquí: sin él, el grupo de NULL es fácil de filtrar por accidente.

        Cuánto costó cada cupón

        El paso 2 resume primero las líneas en una fila por pedido, en una CTE, porque un cupón es una decisión a nivel de pedido: el valor medio del pedido debe dividirse entre pedidos, no entre líneas. A partir de ahí la hoja de costos es una agregación sencilla:

        • revenue: lo que pagaron los clientes, después del descuento;
        • aov: ingresos por pedido;
        • discount_cost: valor antes del descuento menos valor después, el dinero regalado;
        • revenue_share_pct: la porción de cada código en el ingreso neto total, dividida entre una subconsulta escalar (SELECT SUM(net) FROM order_totals) para que el denominador sea el mismo total en todas las filas.

        Comparar lo comparable: los mismos días

        Cada pedido con cupón promedia menos que un pedido sin código. Suena condenatorio, pero los códigos de temporada corren en semanas concretas, y las cestas de Black Friday son más pequeñas en general. La comparación justa pone cada cupón junto a los pedidos hechos los mismos días sin código.

        La segunda CTE, coupon_days, lista los días en que se usó cada código de temporada. Al unirla de vuelta a order_totals por día, obtienes todos los pedidos hechos esos días, una vez por cupón. La agregación condicional los separa:

        AVG(CASE WHEN t.coupon = d.coupon THEN t.net END) AS coupon_aov,
        AVG(CASE WHEN t.coupon = 'none'   THEN t.net END) AS no_coupon_aov

        WELCOME10 y FREESHIP se dejan fuera de este paso porque corren todos los días: para ellos, “los mismos días” significa todo el año.

        Cómo leer el resultado

        coupon coupon_basket coupon_aov no_coupon_aov
        BFCM25 536.54 402.41 483.06
        HOLIDAY20 482.84 386.27 479.56
        SPRING15 634.59 539.40 574.96
        SUMMER15 671.75 570.98 658.07

        La cesta antes del descuento es más o menos igual, o algo superior, a la de un pedido normal esos días. Así que los códigos no hicieron que la gente comprara mucho más; sobre todo pagaron menos por una cesta similar.

        Trampas

        • Un pedido con cupón contado una vez por línea infla orders; cuenta en la CTE a nivel de pedido.
        • Filtrar quantity > 0 importa: tres líneas con cupón tienen cantidad cero o negativa.
        • El costo de FREESHIP es el envío, que no está en estos totales. Menciónalo en lugar de reportar $0.

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