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. A fact row is one sales line; its surrogate keys come from looking up the existing dimensions, not from numbering rows again. Quality gates reject lines with unknown keys, non-numeric or non-positive quantities and invalid dates, and the measure is recomputed by a declared rule (quantity × catalog price).
Dataset: Retail
The tables the challenges use, with their first 6 rows. Under each column name: the kind of value it holds, and which table it links to.
dim_customer5 columns · 848 rows
| customer_keynumber · unique id | customer_idtext | contact_nametext | countrytext | regiontext |
|---|---|---|---|---|
| 1 | 12347 | Arthur Turner | Iceland | Europe |
| 2 | 12353 | Harry Turner | Bahrain | Rest of World |
| 3 | 12359 | Theo Turner | Cyprus | Europe |
| 4 | 12373 | Harry Hill | Austria | Europe |
| 5 | 12374 | Emily Hill | Austria | Europe |
| 6 | 12384 | Ava Moore | Switzerland | Europe |
- customer_keynumber · unique id
- 1
- customer_idtext
- 12347
- contact_nametext
- Arthur Turner
- countrytext
- Iceland
- regiontext
- Europe
- customer_keynumber · unique id
- 2
- customer_idtext
- 12353
- contact_nametext
- Harry Turner
- countrytext
- Bahrain
- regiontext
- Rest of World
- customer_keynumber · unique id
- 3
- customer_idtext
- 12359
- contact_nametext
- Theo Turner
- countrytext
- Cyprus
- regiontext
- Europe
- customer_keynumber · unique id
- 4
- customer_idtext
- 12373
- contact_nametext
- Harry Hill
- countrytext
- Austria
- regiontext
- Europe
- customer_keynumber · unique id
- 5
- customer_idtext
- 12374
- contact_nametext
- Emily Hill
- countrytext
- Austria
- regiontext
- Europe
- customer_keynumber · unique id
- 6
- customer_idtext
- 12384
- contact_nametext
- Ava Moore
- countrytext
- Switzerland
- regiontext
- Europe
first 6 of 848 rows · your queries use all of them
dim_product5 columns · 4,902 rows
| product_keynumber · unique id | product_idtext | descriptiontext | categorytext | pricedecimal |
|---|---|---|---|---|
| 1 | 10002 | INFLATABLE POLITICAL GLOBE | Other Gifts | 0.85 |
| 2 | 10002R | ROBOT PENCIL SHARPNER | Stationery & Gift Wrap | 5.17 |
| 3 | 10080 | GROOVY CACTUS INFLATABLE | Other Gifts | 0.39 |
| 4 | 10109 | BENDY COLOUR PENCILS | Stationery & Gift Wrap | 0.42 |
| 5 | 10120 | DOGGY RUBBER | Other Gifts | 0.21 |
| 6 | 10123C | HEARTS WRAPPING TAPE | Stationery & Gift Wrap | 0.65 |
- product_keynumber · unique id
- 1
- product_idtext
- 10002
- descriptiontext
- INFLATABLE POLITICAL GLOBE
- categorytext
- Other Gifts
- pricedecimal
- 0.85
- product_keynumber · unique id
- 2
- product_idtext
- 10002R
- descriptiontext
- ROBOT PENCIL SHARPNER
- categorytext
- Stationery & Gift Wrap
- pricedecimal
- 5.17
- product_keynumber · unique id
- 3
- product_idtext
- 10080
- descriptiontext
- GROOVY CACTUS INFLATABLE
- categorytext
- Other Gifts
- pricedecimal
- 0.39
- product_keynumber · unique id
- 4
- product_idtext
- 10109
- descriptiontext
- BENDY COLOUR PENCILS
- categorytext
- Stationery & Gift Wrap
- pricedecimal
- 0.42
- product_keynumber · unique id
- 5
- product_idtext
- 10120
- descriptiontext
- DOGGY RUBBER
- categorytext
- Other Gifts
- pricedecimal
- 0.21
- product_keynumber · unique id
- 6
- product_idtext
- 10123C
- descriptiontext
- HEARTS WRAPPING TAPE
- categorytext
- Stationery & Gift Wrap
- pricedecimal
- 0.65
first 6 of 4,902 rows · your queries use all of them
bronze_sales6 columns · 2,526 rows
| row_idnumber · unique id | customer_idtext | product_idtext | quantitytext | salestext | order_datedate |
|---|---|---|---|---|---|
| 123027 | 15687 | 23301 | 24 | 39.60 | 2011-12-01 |
| 123028 | 15687 | 22623 | 3 | 17.85 | 2011-12-01 |
| 123029 | 15687 | 20970 | 4 | 15.00 | 2011-12-01 |
| 123030 | 15687 | 23562 | 6 | 17.34 | 2011-12-01 |
| 123031 | 15687 | 71477 | 4 | 15.80 | 2011-12-01 |
| 123032 | 15687 | 23407 | 2 | 19.90 | 2011-12-01 |
- row_idnumber · unique id
- 123027
- customer_idtext
- 15687
- product_idtext
- 23301
- quantitytext
- 24
- salestext
- 39.60
- order_datedate
- 2011-12-01
- row_idnumber · unique id
- 123028
- customer_idtext
- 15687
- product_idtext
- 22623
- quantitytext
- 3
- salestext
- 17.85
- order_datedate
- 2011-12-01
- row_idnumber · unique id
- 123029
- customer_idtext
- 15687
- product_idtext
- 20970
- quantitytext
- 4
- salestext
- 15.00
- order_datedate
- 2011-12-01
- row_idnumber · unique id
- 123030
- customer_idtext
- 15687
- product_idtext
- 23562
- quantitytext
- 6
- salestext
- 17.34
- order_datedate
- 2011-12-01
- row_idnumber · unique id
- 123031
- customer_idtext
- 15687
- product_idtext
- 71477
- quantitytext
- 4
- salestext
- 15.80
- order_datedate
- 2011-12-01
- row_idnumber · unique id
- 123032
- customer_idtext
- 15687
- product_idtext
- 23407
- quantitytext
- 2
- salestext
- 19.90
- order_datedate
- 2011-12-01
first 6 of 2,526 rows · your queries use all of them
worked example
Run these steps in order to see the idea before you write your own query. The step marked “the pattern” is what the challenges ask for. Running the example does not count toward progress.
Count sales with unknown products. Run this. Lines whose product_id does not match dim_product are rejects—inner joins to the dimension drop them unless you count them first.the pattern
example.sqlSELECT COUNT(*) AS unknown_products FROM bronze_sales b LEFT JOIN dim_product p ON p.product_id = TRIM(b.product_id) WHERE p.product_key IS NULL;
Preview dimension keys for facts. Gold facts must reuse customer_key and product_key from these tables, not invent new ids from Bronze row numbers.
step-2.sqlSELECT customer_key, customer_id, country FROM dim_customer LIMIT 10;
common mistake
An inner join to the dimensions is itself a quality gate: lines with unknown customers or products disappear. Count the rejects so the batch reconciles.