1. Define the fact-table grain and dimensions for Reels engagement reporting.
Support views, watch_time_ms, likes, shares, and saves sliced by creator, viewer country, device type, and day. Choose the row grain, identify which creator and reel attributes need slowly changing dimensions, distinguish additive from non-additive measures, and prevent a viewer action fact from being multiplied by daily summary rows.
I would use one daily row per day, reel, creator SCD version, viewer country, and device type. Views, watch time, likes, shares, and saves are additive. Creator and reel history uses SCD Type 2. Individual viewer actions must be aggregated to that exact daily grain before loading.
This question asks how to organize Reels activity so reports give correct numbers by creator, country, device, and day. First, decide exactly what one stored daily row represents. Next, keep creator and reel details in separate records so older reports can still show the values that were true at the time. The stored numbers must also combine safely when reports cover several days or groups. Finally, individual likes, shares, and saves must be summarized before they are combined with daily totals, or the same daily numbers could be repeated and counted more than once.
- Should historical reports use the creator and reel attributes that were valid when the engagement happened, or always show their current attributes?
- What reporting-day timezone should be used when deriving date_key from event_ts?
- Are viewer country and device type standardized before data reaches the reporting model?
- Can like, share, or save events be reversed or corrected after they arrive?
Start with the grain. Fact_Reels_Engagement_Daily has exactly one row per date_key × reel_key × creator_key × viewer_country_key × device_type_key. Because creator_key and reel_key are surrogate keys for SCD Type 2 dimensions, the grain includes the historical creator and reel versions that apply to that reporting period.
The daily fact contains five foreign keys: date_key, reel_key, creator_key, viewer_country_key, and device_type_key. Its measures are views, watch_time_ms, likes, shares, and saves. These five stored measures are additive across the dimensions shown, so they can be summed when reporting across days, reels, creators, countries, or devices.
Dim_Date contains date_key, date, day, month, quarter, year, and day_of_week. Dim_ViewerCountry contains viewer_country_key, country_code, country_name, region, and subregion. Dim_DeviceType contains device_type_key, device_type, device_category, os_family, and is_mobile. These tables hold descriptive attributes used for slicing instead of placing those descriptions directly in the fact.
Dim_Creator is SCD Type 2. creator_key is its surrogate primary key, while creator_id is the stable business identifier. Historically meaningful attributes such as account_name, category, status, and segment create a new dimension version when they change. effective_from, effective_to, and is_current identify the period for each version. Stable identifiers remain unchanged, while correction-only attributes can be updated as Type 1 when old values do not need to be preserved.
Dim_Reel is also SCD Type 2. reel_key is its surrogate primary key and reel_id is its stable business identifier. Historically meaningful changing attributes include visibility, category, and monetization_state. The immutable fields reel_id and publish_ts remain stable. effective_from, effective_to, and is_current identify each historical reel version. Correction-only fields can be handled as Type 1 when historical preservation is unnecessary.
The separate Fact_Viewer_Action table is an atomic event fact for likes, shares, and saves. Its grain is one viewer action event per row. It contains event_id, event_ts, viewer_id, reel_id, creator_id, viewer_country_key, device_type_key, and action_type.
Before viewer actions contribute to the daily fact, resolve creator_key and reel_key to the SCD Type 2 versions valid as of event_ts, derive date_key, and group by date_key, reel_key, creator_key, viewer_country_key, and device_type_key. Then upsert the aggregated likes, shares, and saves into Fact_Reels_Engagement_Daily at that exact grain.
Do not directly join Fact_Viewer_Action to Fact_Reels_Engagement_Daily when calculating reporting metrics. Several viewer action rows can correspond to one daily summary row. A direct join would repeat that daily row once for each matching action, which can multiply views, watch_time_ms, or other already-aggregated values. Aggregating the atomic actions first prevents that fan-out.
The five stored measures are additive, but derived ratios and averages are non-additive. For example, average watch time should be calculated from the additive components as SUM(watch_time_ms) / SUM(views) at the requested reporting level. Do not sum previously calculated averages.
The main tradeoff is detail versus reporting efficiency. The daily fact is efficient for common reporting because it stores already-aggregated measures at a declared grain. The atomic viewer-action fact keeps event-level like, share, and save detail. Keeping the two grains separate preserves detailed events while preventing event rows from multiplying daily summary measures.
- Declare the daily fact grain as date_key × reel_key × creator_key × viewer_country_key × device_type_key.
- Resolve creator_id and reel_id to the SCD Type 2 surrogate-key versions valid as of event_ts.
- Derive date_key from event_ts using the agreed reporting-day rule.
- Group individual like, share, and save events by the exact five daily fact keys.
- Upsert the aggregated likes, shares, and saves into the matching Fact_Reels_Engagement_Daily row.
- Sum additive stored measures for reporting.
- Recompute ratios and averages from additive components instead of summing derived values.
- Never directly join the atomic action fact to the daily summary fact for metric aggregation.
The daily table makes reporting cheaper because many individual events have already been summarized into one row for each reporting combination. The extra cost is in the data-loading process: it must find the correct historical creator and reel versions, group action events, and update the matching daily rows. SCD Type 2 also stores multiple versions when creator or reel attributes change. The atomic action table uses more storage because it keeps individual events, but it preserves detail for event-level analysis.
This tests whether the candidate can define a precise reporting grain, choose appropriate dimensions and measures, preserve historical creator and reel attributes, distinguish additive measures from derived metrics, and prevent join fan-out from corrupting analytical results.
Common mistakes include choosing an unclear fact grain; storing creator, country, or device descriptions directly in the fact; using creator_id or reel_id without resolving the correct SCD Type 2 version; forgetting viewer_country_key or device_type_key when aggregating atomic actions; summing derived averages such as average watch time; directly joining viewer-action events to daily summary rows and multiplying measures; and combining facts before both sources are at the same grain.
State the grain first, then explain the dimensions, SCD Type 2 history, additive measures, and the fan-out failure case. Emphasize that individual viewer actions are first transformed to exactly the same daily grain before their measures are loaded into the summary fact.









