skip to content

Why must a monthly aggregate fact table join to a shrunken date dimension derived from the day-level one?

level: middleimportance: must knowfreq 50%

answer

  1. where do the month labels come from?
  2. two tables, one set of attributes
  3. what happens when finance moves the fiscal year?
  4. subset of attributes, identical values
  5. conformed rollup, derived from the base dimension

basics

~20 s

Because the month dimension must be a rollup of the day dimension's attributes and labels. Building it separately lets month names, fiscal periods and hierarchies drift, so the aggregate and the atomic star report different things for the same month.

solid answer

~50 s

A **shrunken dimension** is a conformed dimension rolled up to the aggregate's grain: a month table produced from the day-level date dimension, or a category table produced from the product dimension. It must be *derived* from the base dimension, keeping a strict subset of its attributes with identical values. The reason is conformance. If someone builds a month table independently — parsing dates, hand-typing fiscal quarters — the two tables will eventually disagree: a fiscal-year boundary changes in one and not the other, a label reads `Jan-24` here and `January 2024` there, a category is renamed in the product dimension but not in its copy. Then the same business question returns different answers depending on which table the query hit, and drilling from month down to day loses rows or gains them. Deriving the shrunken dimension makes that impossible by construction: the attributes exist in exactly one place, and the rollup is regenerated whenever the base dimension changes.

code

sql · 12 lines
sql
-- shrunken (rolled-up) month dimension, derived from the day-grain one
CREATE TABLE dim_month AS
SELECT DISTINCT
       month_key,            -- 202401
       month_name,           -- 'January 2024'
       calendar_quarter,
       calendar_year,
       fiscal_quarter,
       fiscal_year
FROM   dim_date;
-- excluded on purpose: date_key, day_of_week, is_holiday
--   (not single-valued within a month)

go deeper

for a junior

Know the term: a shrunken dimension is a conformed dimension rolled up to the aggregate's grain, such as a month table made from the date dimension. It holds fewer attributes, never different ones.

for a middle

Explain the derivation and the test for which attributes survive — an attribute belongs only if it is single-valued at the coarser grain — and give a concrete drift example such as a changed fiscal calendar.

for a senior

Show that you treat the rollup as part of the base dimension's load, and be ready to diagnose a live disagreement between a monthly and a daily report back to a divergent attribute source.

for a principal

Own conformance as a platform rule: attributes defined once, rollups generated, and no team permitted to hand-build a period or hierarchy table beside the published dimension.

## What a shrunken dimension is When you build an aggregate fact table at a coarser grain, its foreign keys can no longer point at the base dimensions. A fact row that means "this product, this store, this **month**" cannot carry a day-level `date_key`. It needs a dimension whose rows *are* months. A **shrunken dimension** (also called a rolled-up dimension) is that table: a conformed dimension reduced to the aggregate's grain, containing a strict subset of the base dimension's attributes with exactly the same values. `dim_month` is `dim_date` shrunk; `dim_product_category` is `dim_product` shrunk. **Conformed** means the two tables agree: every attribute that appears in both carries identical content and identical labels, so a filter or a grouping means the same thing on either. ## Derive it, never build it beside The correct construction is a projection of the base dimension: ```sql CREATE TABLE dim_month AS SELECT DISTINCT month_key, -- e.g. 202401 month_name, -- 'January 2024' calendar_quarter, calendar_year, fiscal_month_number, fiscal_quarter, fiscal_year FROM dim_date; ``` Every attribute in `dim_month` came from `dim_date`. There is no second definition of what fiscal Q1 is, no second spelling of the month label, no second opinion about which months belong to which year. The tempting alternative — generating a month table from scratch, or deriving month strings from the aggregate's own data — creates a parallel source for the same attributes. Parallel sources drift. Concretely: - Finance changes the fiscal calendar. Someone updates `dim_date`; the standalone month table keeps last year's boundaries, and monthly fiscal reports diverge from daily ones. - The month label is formatted `Jan-24` in one table and `January 2024` in the other. A drill-across report placing both on one row shows two labels for the same period, and any join or union on the label silently drops rows. - A product category is renamed. The product dimension picks it up; the hand-built category table does not, so category revenue no longer ties out to the sum of its products. None of these produce an error. They produce two credible numbers, which is worse. ## Only attributes that survive the rollup A shrunken dimension may keep only the attributes that are single-valued *at its grain*. `month_name`, `calendar_quarter` and `fiscal_year` are constant within a month, so they belong. `day_of_week`, `is_holiday` and the specific `date_key` are not constant within a month and must be dropped — including one of them would force an arbitrary choice (the first day? the last?) and any filter on it would return a nonsensical subset of months. The same test governs a product rollup: `category_name` is constant within a category and belongs; `unit_price` and `sku` vary within it and do not. Applying the test is precisely the discipline that makes the shrunken dimension trustworthy, and it is the reason candidates who say "just copy the dimension and group it" get pushed on in interviews. ## The key strategy The shrunken dimension needs its own key at its own grain: a `month_key` that already exists as an attribute of the date dimension, or a surrogate assigned to each category. What it must **not** do is reuse a base-dimension row's key to stand for the whole group — pointing the month aggregate at the first day of the month, for instance. That works until someone filters on a day-level attribute and gets "all months whose first day was a Monday", or until a report joins the aggregate to the day dimension and each month row matches exactly one day rather than the period it represents. ## Why this makes aggregate navigation possible A BI or semantic layer can only redirect a monthly query to the aggregate if grouping by `month_name` there yields the same labels and the same row set as grouping by `month_name` on the star. Conformance is the precondition; the shrunken dimension is how you obtain it. Without it, substitution is unsafe and the aggregate must be queried explicitly by people who know its quirks — which is how organizations end up with two revenue numbers. ## Regenerate it with the base Because it is derived, the shrunken dimension has to be rebuilt or merged whenever the base dimension changes. Treat that as part of the dimension's own load, not as a separate job someone might forget: the moment the two are refreshed on independent schedules, they can disagree for a whole day at a time, and a report run in that window is unreproducible. ## What interviewers listen for The words *conformed* and *derived*, the test that an attribute must be single-valued at the aggregate's grain, and a concrete drift example. Candidates who treat the month table as a trivial calendar utility usually have not been on the receiving end of two fiscal calendars.

  • Which attributes of a day-level date dimension may appear in the shrunken month dimension?
    Only those that are single-valued at month grain: month name, calendar quarter, calendar year, fiscal period. Day-of-week, holiday flags and the day key vary within the month and must be dropped — keeping one would force an arbitrary choice of day and make any filter on it meaningless.
  • Can the monthly aggregate just point at the first day of each month in the day dimension instead?
    No. It looks convenient but the row still carries day-level attributes, so a filter on day-of-week or a holiday flag silently returns a strange subset of months, and a reader cannot tell whether the row means one day or one month. The grain must be represented by a dimension row that genuinely is a month.
  • When the base product dimension gets a new attribute, what happens to the shrunken category dimension?
    Nothing automatically, and that is the risk. Add the attribute to the rollup only if it is single-valued per category, and regenerate the shrunken table as part of the base dimension's own load so the two never refresh on independent schedules and disagree in between.

saying these in an interview costs you the question

  • Generating the month table separately from the date dimension
  • Copying day-level attributes into a month-grain dimension
  • Pointing a month aggregate at the first day of the month
  • Assuming labels will match because both came from dates
  • Refreshing the rollup dimension on its own schedule

context