06 · Step 4
Choose keys and history
⏱ 9 min · Topic 6 of 11
Say the keys out loud. Each dimension gets a surrogate key. That is a new number made by the warehouse, as chapter 3 taught.
In this chapter the new keys use the same numbers as the old ids, to keep the rows easy to read. The date key is the date as a number: 2026-01-03 becomes 20260103.
The key of each fact is its grain. In fact_orders it is order_id. In fact_order_items it is order_id and product_key together.
Now handle the missing country. Dev has no country.
Store the word Unknown in dim_customer. Then the report shows a clear label, not a blank.
History for country
The interviewer said old orders keep the old country. That needs history, as in chapter 11. Use a type 2 change: add a new row, and never overwrite the old one.
Suppose Asha moves to DE on 2026-02-01. This table shows her two rows in dim_customer. A valid_to of NULL means the row is current:
dim_customer after the move (Asha only)
| customer_key | customer_id | country | valid_from | valid_to |
|---|
| 1 | 1 | IN | 2026-01-01 | 2026-01-31 |
| 6 | 1 | DE | 2026-02-01 | NULL |
Orders 101 and 102 still point at customer_key 1, so they stay in IN. A new order after 2026-02-01 uses customer_key 6, so it counts in DE.
The cost is real. One customer is now two rows, so COUNT(*) counts Asha twice.
Use COUNT(DISTINCT customer_id) instead. It counts each customer once.
What you say: “Surrogate keys, flat dimensions, and type 2 history on country. Each fact is keyed by its grain.”