La solicitud

De Kevin Brooks, Gerente de Operaciones

“Para la revisión anual de operaciones quiero una tabla, no tres: pedidos completados, devoluciones y sesiones del sitio web por mes de 2025, todo en las mismas columnas para poder graficarlos juntos.”

Tu objetivo

Devuelve una tabla para 2025 con las columnas metric, month y value. metric es 'orders' para los pedidos completados contados por el mes de order_date, 'returns' para las devoluciones contadas por el mes de returned_on, y 'sessions' para web_sessions contadas por el mes de started_at. month es el primer día del mes como DATE. Ordena por month y luego por metric.

  • Lee de la tabla orderspendiente
  • Lee de la tabla returnspendiente
  • Muestra exactamente metric month valuependiente

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

    Un join pone dos tablas una al lado de otra: más columnas. UNION ALL pone dos resultados de consulta uno encima de otro: más filas. Lo usas siempre que el mismo tipo de número vive en distintas tablas y lo quieres en un solo resultado.

    Cómo funciona UNION ALL

    SELECT 'orders' AS metric, CAST(DATE_TRUNC('month', order_date) AS DATE) AS month, COUNT(*) AS value
    FROM orders
    WHERE status = 'completed' AND order_date >= '2025-01-01' AND order_date < '2026-01-01'
    GROUP BY month
    UNION ALL
    SELECT 'returns', CAST(DATE_TRUNC('month', returned_on) AS DATE), COUNT(*)
    FROM returns
    WHERE returned_on >= '2025-01-01' AND returned_on < '2026-01-01'
    GROUP BY 2
    ORDER BY month, metric;

    Cada SELECT es una consulta completa con su propio FROM, WHERE y GROUP BY. La base de datos los ejecuta por separado y apila los resultados. Se aplican tres reglas:

    • todos los SELECT devuelven el mismo número de columnas,
    • las columnas se emparejan por posición, no por nombre, así que los tipos de cada posición deben ser compatibles,
    • los nombres de columna del resultado vienen del primer SELECT. Por eso solo el primero necesita alias.

    ORDER BY se escribe una sola vez, al final del todo, y ordena las filas combinadas.

    La columna de etiqueta

    Sin 'orders' AS metric, obtendrías una columna de meses y conteos sin forma de saber qué número es cuál. Una columna constante de texto es el truco estándar: viaja con cada fila de su SELECT y se convierte en el nombre de la serie en un gráfico.

    Con los datos de Harbor & Pine, enero de 2025 sale con 268 pedidos completados, 64 devoluciones y 960 sesiones. Noviembre salta a 651 pedidos y 2,609 sesiones: la temporada navideña se ve en las tres métricas a la vez, que es justo por lo que Kevin las quiere en una tabla.

    Este formato “largo” (métrica, periodo, valor) es el que esperan la mayoría de las herramientas de gráficos y los paneles de BI. Si alguien quiere después una columna por métrica, la agregación condicional del capítulo 6 lo pivota de vuelta.

    Errores comunes

    • ORDER BY dentro de una rama. ... GROUP BY month ORDER BY month UNION ALL SELECT ... es un error de sintaxis. Ordena una sola vez, después del último SELECT.
    • Columnas en distinto orden. Si el segundo SELECT devuelve el conteo antes del mes, la base de datos empareja por posición e intenta poner un número en la columna de fecha. Algunos motores dan error, otros convierten en silencio, y en ambos casos obtienes un sinsentido.
    • Granos de fecha distintos. Agrupar pedidos por mes y sesiones por día se apila bien pero hace un gráfico que no significa nada. Mantén el mismo grano en todas las ramas.
    • Filtros distintos. Si una rama cubre 2025 y otra olvidó su filtro de fechas, el apilado se ejecuta igual. Lee todas las cláusulas WHERE una junto a otra.

    En SQL Server

    UNION ALL funciona igual. Los inicios de mes suelen escribirse DATEFROMPARTS(YEAR(order_date), MONTH(order_date), 1) (o DATETRUNC(month, order_date) desde SQL Server 2022), y agrupas por la expresión en lugar de por la posición, porque T-SQL no acepta GROUP BY 2.

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