runtime
73 / 88

lesson 73 Warehouse & reporting projects · advanced

Gold: dimensions, facts & quality gates

Build dimensions and facts with checks for trustworthy data.

the idea

Gold presents business entities and measures. Dimensional surrogate keys come from the existing dimension lookup, not a new ROW_NUMBER on every load. One fact row is one sales line. For this exercise reject unknown keys, invalid dates, and nonpositive/nonnumeric quantities; recompute sales from quantity × catalog price.

tables in this lesson

The challenges use this data. Each column shows its type underneath; → marks a link to another table.

bronze_sales6 columns · 13 rows
row_idinteger · keycustomer_idtextproduct_idtextquantitytextsalestextorder_datetext
1C001P012242025-01-01
2 C002 P031802025-01-02
3C001P021452025-01-15
4C003P0422402025-02-01
5C004P0321602025-02-05

showing 5 of 13 rows

dim_customer4 columns · 5 rows
customer_keyinteger · keycustomer_idtextnametextcountrytext
1C001Alice NguyenUnited States
2C002BenUnited Kingdom
3C003CaraUnited Kingdom
4C004DevIndia
5C005ElenaCanada

all 5 rows

dim_product5 columns · 4 rows
product_keyinteger · keyproduct_idtextnametextcategorytextpricereal
1P01NotebookStationery12
2P02Desk lampHome45
3P03KeyboardTech80
4P04HeadphonesTech120

all 4 rows

example

The idea in one query. Press Run to see what it returns; running examples never affects your progress.

example.sql
CREATE TEMP TABLE built_fact AS
SELECT
  b.row_id AS sale_key,
  c.customer_key,
  p.product_key,
  CAST(b.quantity AS INTEGER) AS quantity,
  CAST(b.quantity AS INTEGER)*p.price AS sales,
  b.order_date
FROM bronze_sales b
JOIN dim_customer c ON c.customer_id=TRIM(b.customer_id)
JOIN dim_product p ON p.product_id=TRIM(b.product_id)
WHERE TRIM(b.quantity)<>''
  AND TRIM(b.quantity) NOT GLOB '*[^0-9]*'
  AND CAST(b.quantity AS INTEGER)>0
  AND b.order_date GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
  AND date(b.order_date,'+0 days')=b.order_date;
SELECT *
FROM built_fact;

Watch for: Recomputed sales is a declared business rule here, not a universally valid correction to source accounting data.

build it step by step

Each step changes one thing. Run them in order and watch the result change.

  1. Inspect Bronze sales before Gold. Gold maps cleaned keys into dimensions and facts. Read bronze_sales fields that will become fact grain and measures.

    step-1.sql
    SELECT row_id, customer_id, product_id, quantity, order_date
    FROM bronze_sales
    ORDER BY row_id
    LIMIT 8;
  2. Assemble a fact with dimension keys. Join Bronze rows to dimension surrogates, cast measures, and materialize the fact. Quality gates check counts and orphans.

    step-2.sql
    CREATE TEMP TABLE built_fact AS
    SELECT
      b.row_id AS sale_key,
      c.customer_key,
      p.product_key,
      CAST(b.quantity AS INTEGER) AS quantity,
      CAST(b.quantity AS INTEGER)*p.price AS sales,
      b.order_date
    FROM bronze_sales b
    JOIN dim_customer c ON c.customer_id=TRIM(b.customer_id)
    JOIN dim_product p ON p.product_id=TRIM(b.product_id)
    WHERE TRIM(b.quantity)<>''
      AND TRIM(b.quantity) NOT GLOB '*[^0-9]*'
      AND CAST(b.quantity AS INTEGER)>0
      AND b.order_date GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
      AND date(b.order_date,'+0 days')=b.order_date;
    SELECT *
    FROM built_fact;

challenge 1

Build TEMP built_fact from bronze_sales and dimension lookups. Validate numeric positive quantity, valid date and matching trimmed natural keys. Recompute sales = quantity × dim_product.price. Return sale_key,customer_key,product_key,quantity,sales,order_date.

Return sale_keycustomer_keyproduct_keyquantitysalesorder_dateany row ordertable changes are checked too

challenge-1.sql
 
To master this lesson, solve both challenges without hints and pass the concept check. 3 of 3 to go.