1. Faro

Nivel 2 · Unidades e ingresos totales

La solicitud

De Brian Mitchell, Analista de Finanzas

“Necesito una cifra principal para la presentación de ventas de todos los tiempos: cuántas líneas de pedido, cuántas unidades y los ingresos netos totales después de descuentos. Deja fuera las líneas con cantidad cero o negativa, son errores de datos.”

Tu objetivo

Desde order_items, considerando solo las filas con quantity > 0, devuelve una fila con: line_count (número de líneas), total_units (suma de quantity) y net_revenue (suma de quantity * unit_price * (1 - discount_pct / 100.0), redondeada a 2 decimales). Incluye todos los pedidos sin importar su estado.

  • Lee de la tabla order_itemspendiente
  • Muestra exactamente line_count total_units net_revenuependiente
  • 1 filapendiente

Tu consulta

SQL

Cargando el editor…

    ResultadoVista previa de order_items · presiona Ejecutar para ver el tuyo
    Vista previa de order_items
    order_item_idorder_idproduct_idquantityunit_price
    11001121931.99
    21001154311.99
    31002154411.99
    410021941149.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.

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

    SUM, AVG, MIN y MAX funcionan como COUNT: colapsan filas en un solo valor. Reciben una columna o cualquier expresión:

    SELECT
      SUM(quantity) AS total_units,
      AVG(unit_price) AS avg_line_price,
      MIN(unit_price) AS cheapest_line,
      MAX(unit_price) AS priciest_line
    FROM order_items;

    Los ingresos se calculan por línea y luego se suman

    En Harbor & Pine cada línea de pedido guarda la cantidad, el precio unitario al momento de la venta y un descuento en porcentaje (15.0 significa 15 % de descuento). Los ingresos netos de una línea son:

    quantity * unit_price * (1 - discount_pct / 100.0)

    Dividir entre 100.0 en lugar de 100 es un hábito de portabilidad: si discount_pct fuera una columna entera, Postgres calcularía 15 / 100 como 0 y descartaría todos los descuentos sin avisar.

    Pon toda la expresión dentro de SUM. No multipliques sumas entre sí: SUM(quantity) * SUM(unit_price) es un número sin sentido. La regla es calcular a nivel de fila, agregar una sola vez.

    Fíjate en que order_items.unit_price es el precio pagado, que puede diferir del products.unit_price de hoy tras un cambio de precio. Los ingresos siempre usan el precio de la línea de pedido.

    Excluir filas erróneas, en voz alta

    Un puñado de líneas tiene cantidades cero o negativas. Brian pidió excluirlas, así que la consulta tiene WHERE quantity > 0. En el trabajo, declara siempre las exclusiones en tu respuesta (“excluye 24 líneas con quantity <= 0”). Cuando finanzas concilie tu número con el suyo, esa frase ahorra una hora.

    Cómo trata AVG los NULL

    Como COUNT(columna), SUM, AVG, MIN y MAX ignoran los NULL. AVG(unit_cost) sobre productos es el promedio de los costos conocidos. Normalmente es lo correcto, pero significa que AVG(x) no siempre es SUM(x) / COUNT(*):

    SELECT
      AVG(unit_cost) AS avg_known_cost,           -- ignores NULLs
      SUM(unit_cost) / COUNT(*) AS treats_null_as_0 -- different number
    FROM products;

    Si todos los valores son NULL, SUM devuelve NULL, no 0. Envuélvelo en COALESCE(SUM(x), 0) cuando un informe necesite un cero.

    Promedios de promedios

    Una trampa clásica: el valor promedio de pedido son los ingresos totales divididos entre el número de pedidos, no el promedio de los ingresos por línea. Las líneas y los pedidos son granos distintos, y un promedio depende de sobre cuál se promedia. Pregúntate siempre “¿una fila por qué?” antes de escribir AVG.

    Errores comunes

    • Redondear dentro de la suma: SUM(ROUND(...)) acumula errores de redondeo. Redondea el resultado final.
    • Usar AVG(discount_pct) como “el descuento promedio”. Pondera igual una línea de $5 que una de $900. Un descuento ponderado por ingresos es 100 * (1 - SUM(quantity * unit_price * (1 - discount_pct / 100.0)) / SUM(quantity * unit_price)).

    En SQL Server

    SUM, AVG, MIN y MAX ignoran los NULL de la misma manera. Ojo con AVG sobre una columna INT: devuelve un INT allí, así que AVG(quantity) sobre las líneas limpias da 1 en lugar de 2.00 (el promedio real es 1.998). Convierte primero, y usa ISNULL o COALESCE para los valores alternativos:

    SELECT AVG(CAST(quantity AS decimal(10, 2))) AS avg_units
    FROM order_items
    WHERE quantity > 0;

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