Slowly Changing Dimensions (SCD)

Context: FIT3003_MOC Β· Building Dimension Tables assumes a member’s attributes never move β€” SCD is the answer when they do Β· (Chapter 6; verified against the W12 revision chapter) Parent Framework: Star Schema

Quick Revision

  • 🎯 Objective: fold the temporal (historical) aspect of a dimension record into the warehouse βž” a measure must be reportable against the attribute value that was true at the time of the fact, not the value true today.
  • πŸ“¦ Core Components: Types 0 / 1 βž” no history at all | Types 2 / 3 / 6 βž” history kept inside the dimension | Type 4 βž” history split into a separate table (a bridge / weak entity).
  • ⚑ Key Constraint: overwriting a changed attribute silently re-prices the past β€” every historic fact row is then reported at the current value.

πŸ“ How It Works

1. The failure it fixes β€” Bookshop case study

  • Temporal attribute βž” an attribute whose value has a life-time (C1’s price \45.95(\text{StartDate}, \text{EndDate})$ pair.
  • β€œSlowly” βž” for records that change slowly over time (a book’s price) β›” not applicable to rapidly changing data Β· original types 1, 2, 3; newer types 0, 4, 6.
  • Operational source βž” joined to , with price history held apart in .
  • The naive star βž” with the current Price stored flat inside .
  • Symptom βž” CSIRO Diet (C1) sells far more in Dec2007, yet the report shows \45.95$30.95$10.00$ β€” arithmetically correct, commercially wrong.
  • C1’s real history βž” Jan2007–Jul2007 \45.95$36.7520%$23.00$45.95$ full βž” the Dec2007 spike was the discount.
  • Open-ended sentinel βž” the current price row carries , so β€œthe price now” is a range test, not a max().
  • After the fix βž” a second measure can be added to once the price valid at sale time is reachable.

2. The type ladder

  • Type 0 β€” original βž” stores the initial value of the record and never touches it again.
  • Type 1 β€” latest βž” overwrites with the latest value (H6 βž” \10.00$). Shared weakness of 0 and 1 βž” neither records the history of changes at all.
  • Type 2 β€” versioned rows βž” history is not separated from the main dimension; new records keep being added: gains and a sequence number is appended to the original BookID (C1_1 … C1_4, H6_1 … H6_3, DV_1) β€” each version is its own member, and the fact’s FK points at the version: Dec2007 sales carry C1_3, Mar2008 sales C1_4.
  • Type 3 β€” previous column βž” a simplification of Type 2 assuming the complete history is not necessary: one row per member, CurrentPrice beside PreviousPrice (C1 \45.95 / $23.00$10.00 / $30.95$27.95 /$ Null when never changed).
  • Type 4 β€” history table βž” a new dimension holds the full change history; keeps only the stable attributes and the price columns move to . The same book keeps one BookID.
  • Type 4 for a changed business rule (W11) βž” when Semester 1’s end date moves (15 Jul βž” 30 Jun from 2021), keeps both versions, EndYear null marking the one in force βž” Active Data Warehousing.
  • Type 6 β€” 2 3 βž” no separate identifier for the same book, but the entire history is kept: one row per version, each carrying its own CurrentPrice and the PreviousPrice before it (C1: Null βž” βž” βž” ): .

3. Type 6 breaks the star’s cardinality

  • The problem βž” BookID now repeats across versions, so β€” is no longer – but –: a fact row’s BookID matches every version of that book.
  • Three fixes βž” β‘  add a new surrogate key to (Surrogate Key) β‘‘ add to the fact, beside BookID β‘’ add an associative (bridge) table between and the fact (Bridge Tables).

βš™οΈ Core Implementation

πŸ”Ή Type 4 β€” the shape the lecture builds

πŸ”Ή Type 4 β€” the correct report (range join listagg)

βš–οΈ Core Decision Matrix

TypeWhere history livesRows per memberRecovers the price at sale time?Cost
0nowhere β€” initial value frozen1❌reports drift as reality moves
1nowhere β€” overwritten1❌the past is silently re-priced
2in the dimension, as extra rows with suffixed IDsmanyβœ… fullone book is split across version IDs; CurrentFlag finds β€œnow”
3in the dimension, as extra columns1⚠️ one step back onlyanything older than the previous value is lost
4in a separate dimension1 history rowsβœ… fullone more join (a range join) per historic query
6both (2 3)many, same BookIDβœ… full previous valuedimension–fact becomes – βž” needs a fix (Β§3)

When It Flips: Type 3 is enough only while "the previous value" is the whole business question. The moment a report must span more than one change β€” C1 went full price βž” off βž” half price βž” full price β€” Types 2, 4 or 6 are the only correct answers.

⚠️ Common Mistakes

  • πŸ’‘ Treating Type 0 and Type 1 as different for reporting βž” they differ in which single value survives, not in whether history exists; both answer historic questions wrong.
  • πŸ’‘ Keying a Type 6 fact on BookID alone βž” the ID repeats per version, so each fact row joins every version and the measure multiplies β€” apply one of the three Β§3 fixes.
  • πŸ’‘ Calling Type 4’s history table a plain dimension βž” its key is the composite ; it is a weak-entity / bridge-shaped table hanging off the parent, not a second axis of the star.

🧠 Active Recall