1. Faro

Nivel 2 · Guarda un resumen como tabla

La solicitud

De Brian Mitchell, Analista Financiero

“Sigo repitiendo los mismos números de categoría de 2025 para cada presentación. ¿Puedes guardarlos como una tabla que pueda consultar, y darme los ingresos por pedido a partir de ella?”

Tu objetivo

Crea una tabla category_sales_2025 a partir de los pedidos completados realizados en 2025 (líneas con quantity > 0) con una fila por categoría: category, orders (pedidos distintos), units (suma de quantity) y net_revenue (suma de quantity * unit_price * (1 - discount_pct / 100.0), redondeada a 2). Luego consulta esa tabla y devuelve category, orders, units, net_revenue y revenue_per_order (net_revenue / orders, redondeado a 2), ordenado por net_revenue descendente.

  • Lee de la tabla productspendiente
  • Lee de la tabla orderspendiente
  • Muestra exactamente category orders units net_revenue revenue_per_orderpendiente

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.

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

    Cuando la misma consulta costosa alimenta varios informes, guarda su resultado una vez y consulta la copia guardada. CREATE TABLE ... AS SELECT, a menudo abreviado CTAS, hace exactamente eso.

    CREATE TABLE AS SELECT

    CREATE TABLE category_sales_2025 AS
    SELECT p.category,
           COUNT(DISTINCT o.order_id) AS orders,
           SUM(i.quantity) AS units,
           ROUND(SUM(i.quantity * i.unit_price * (1 - i.discount_pct / 100.0)), 2) AS net_revenue
    FROM order_items AS i
    JOIN orders AS o ON o.order_id = i.order_id
    JOIN products AS p ON p.product_id = i.product_id
    WHERE o.status = 'completed' AND i.quantity > 0
      AND o.order_date >= '2025-01-01' AND o.order_date < '2026-01-01'
    GROUP BY p.category;

    No hay lista de columnas: la nueva tabla toma sus nombres de columna de los alias de la consulta y sus tipos de las expresiones. Por eso los buenos alias importan aquí. Un SUM(...) sin nombre se convertiría en una columna llamada algo como sum(i.quantity), que es un fastidio de escribir en cada consulta posterior.

    Consulta la tabla guardada

    El resultado es una tabla normal con seis filas, una por categoría. Las consultas posteriores la leen como cualquier otra:

    SELECT category, orders, units, net_revenue,
           ROUND(net_revenue / orders, 2) AS revenue_per_order
    FROM category_sales_2025
    ORDER BY net_revenue DESC;

    Furniture encabeza 2025 con $573,909.05 de 560 pedidos, así que un pedido de Furniture aporta unos $1,024.84 de ingresos de Furniture. Decor aparece en más pedidos (2,155) pero a $134.82 por pedido. Lighting queda en el medio con $385,144.61 de 1,221 pedidos.

    Una tabla guardada es una instantánea. Si mañana se registra un reembolso, category_sales_2025 no cambia hasta que la reconstruyas. Una vista (CREATE VIEW name AS SELECT ...) es la alternativa: guarda la consulta, no las filas, así que siempre está al día pero se recalcula cada vez que la lees. Los analistas usan tablas para instantáneas de informes diarios y vistas para la lógica que debe estar siempre actualizada.

    Tablas de preparación en la práctica

    Los pipelines reales las encadenan: una tabla de preparación con las líneas de pedido limpias, una tabla de resumen construida a partir de ella, y un panel que lee el resumen. Cada paso es pequeño, tiene nombre y se puede comprobar por sí solo, la misma idea que una cadena de CTE, salvo que los resultados intermedios persisten.

    En este juego cada ejecución se revierte, así que la tabla existe solo durante las sentencias de esa ejecución. Por eso la solución la crea y la consulta de una vez.

    Errores comunes

    • Falta el punto y coma entre las dos sentencias. La base de datos ve entonces una sola sentencia larga y rota.
    • Dejar los agregados sin alias, de modo que las nuevas columnas reciben nombres generados incómodos.
    • Ejecutar CREATE TABLE dos veces en una base de datos real: la segunda vez falla porque la tabla ya existe. Usa CREATE OR REPLACE TABLE (DuckDB, Snowflake, BigQuery) o elimínala antes.
    • Olvidar que la tabla es una instantánea y presentar números desactualizados.

    En SQL Server

    T-SQL no tiene CREATE TABLE ... AS SELECT. Escribes SELECT ... INTO, que crea la tabla a partir de la consulta:

    SELECT Category, COUNT(*) AS Orders
    INTO dbo.CategorySales2025
    FROM ...;

    Postgres, DuckDB, Snowflake y BigQuery usan CREATE TABLE ... AS; MySQL también lo acepta.

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