fix(dimensional): fix dim_discount grain mismatch causing tfact_order fan-out - #2411
Open
blarghmatey wants to merge 4 commits into
Open
fix(dimensional): fix dim_discount grain mismatch causing tfact_order fan-out#2411blarghmatey wants to merge 4 commits into
blarghmatey wants to merge 4 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a dimensional grain mismatch in dim_discount that could cause tfact_order to fan out when joining discounts, by ensuring dim_discount emits exactly one row per (source_discount_id, platform_code) and aligning the surrogate key with that grain.
Changes:
- Dedupes
dim_discountto one row per(platform_code, source_discount_id), keeping the most recently updated record. - Updates
discount_pkgeneration to hash only(source_discount_id, platform_code)to match documented/consumed grain. - Clarifies
discount_codedocumentation to reflect that it may represent the latest code on file.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/ol_dbt/models/dimensional/dim_discount.sql | Adds a dedupe step and adjusts surrogate key generation to prevent downstream fact fan-out. |
| src/ol_dbt/models/dimensional/_dim__models.yml | Updates discount_code column description to match the new deduped “latest code” behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
blarghmatey
added a commit
that referenced
this pull request
Jul 9, 2026
…test Add discount_code as a final ORDER BY tie-breaker in the dedup row_number() so the surviving row is deterministic even when updated_on/created_on are identical (or both null) across duplicate source rows for the same (source_discount_id, platform_code) — previously the pick could vary between runs. Also add an explicit dbt_utils.unique_combination_of_columns test on (source_discount_id, platform_code), the now-documented and consumed grain, so future grain drift is caught directly rather than only via the downstream discount_pk uniqueness test. Addresses review feedback on #2411 from Copilot.
blarghmatey
added a commit
that referenced
this pull request
Jul 10, 2026
…discount_fk dim_discount is materialized='table' (full-refresh every run) but tfact_order is incremental with delete+insert on order_key, not discount_fk. Changing discount_pk's hash inputs (as this PR does) regenerates every discount_pk on the next dim_discount run, orphaning discount_fk on historical tfact_order rows until tfact_order is also full-refreshed. Document the required deploy step inline (matching the existing tfact_problem_events full-refresh note) so it isn't missed. Addresses review feedback on #2411 from sentry[bot].
blarghmatey
added a commit
that referenced
this pull request
Jul 11, 2026
…test Add discount_code as a final ORDER BY tie-breaker in the dedup row_number() so the surviving row is deterministic even when updated_on/created_on are identical (or both null) across duplicate source rows for the same (source_discount_id, platform_code) — previously the pick could vary between runs. Also add an explicit dbt_utils.unique_combination_of_columns test on (source_discount_id, platform_code), the now-documented and consumed grain, so future grain drift is caught directly rather than only via the downstream discount_pk uniqueness test. Addresses review feedback on #2411 from Copilot.
blarghmatey
added a commit
that referenced
this pull request
Jul 11, 2026
…discount_fk dim_discount is materialized='table' (full-refresh every run) but tfact_order is incremental with delete+insert on order_key, not discount_fk. Changing discount_pk's hash inputs (as this PR does) regenerates every discount_pk on the next dim_discount run, orphaning discount_fk on historical tfact_order rows until tfact_order is also full-refreshed. Document the required deploy step inline (matching the existing tfact_problem_events full-refresh note) so it isn't missed. Addresses review feedback on #2411 from sentry[bot].
blarghmatey
force-pushed
the
worktree-dbt-warehouse-audit
branch
from
July 11, 2026 00:55
4d48985 to
2ff33e3
Compare
🔎 ol-dbt impact — column-level blast radius✅ No column-level downstream impact detected for the changed models. Posted by |
blarghmatey
added a commit
that referenced
this pull request
Jul 16, 2026
…test Add discount_code as a final ORDER BY tie-breaker in the dedup row_number() so the surviving row is deterministic even when updated_on/created_on are identical (or both null) across duplicate source rows for the same (source_discount_id, platform_code) — previously the pick could vary between runs. Also add an explicit dbt_utils.unique_combination_of_columns test on (source_discount_id, platform_code), the now-documented and consumed grain, so future grain drift is caught directly rather than only via the downstream discount_pk uniqueness test. Addresses review feedback on #2411 from Copilot.
blarghmatey
added a commit
that referenced
this pull request
Jul 16, 2026
…discount_fk dim_discount is materialized='table' (full-refresh every run) but tfact_order is incremental with delete+insert on order_key, not discount_fk. Changing discount_pk's hash inputs (as this PR does) regenerates every discount_pk on the next dim_discount run, orphaning discount_fk on historical tfact_order rows until tfact_order is also full-refreshed. Document the required deploy step inline (matching the existing tfact_problem_events full-refresh note) so it isn't missed. Addresses review feedback on #2411 from sentry[bot].
blarghmatey
force-pushed
the
worktree-dbt-warehouse-audit
branch
from
July 16, 2026 14:06
2ff33e3 to
943dec6
Compare
5 tasks
… fan-out dim_discount hashed discount_pk from (source_discount_id, discount_code, platform_code), but the docs and tfact_order's join both assume (source_discount_id, platform_code) is the unique grain. When a discount's code changes over its lifetime, that assumption broke: dim_discount emitted multiple rows per (source_discount_id, platform_code), tfact_order's join fanned out, and the final dedup picked an arbitrary discount_fk since order_updated_on was identical across the fanned rows. Dedupe dim_discount to one row per (source_discount_id, platform_code), keeping the most recently updated discount_code, and hash the surrogate key from just those two columns. Fixes #2379
…test Add discount_code as a final ORDER BY tie-breaker in the dedup row_number() so the surviving row is deterministic even when updated_on/created_on are identical (or both null) across duplicate source rows for the same (source_discount_id, platform_code) — previously the pick could vary between runs. Also add an explicit dbt_utils.unique_combination_of_columns test on (source_discount_id, platform_code), the now-documented and consumed grain, so future grain drift is caught directly rather than only via the downstream discount_pk uniqueness test. Addresses review feedback on #2411 from Copilot.
…discount_fk dim_discount is materialized='table' (full-refresh every run) but tfact_order is incremental with delete+insert on order_key, not discount_fk. Changing discount_pk's hash inputs (as this PR does) regenerates every discount_pk on the next dim_discount run, orphaning discount_fk on historical tfact_order rows until tfact_order is also full-refreshed. Document the required deploy step inline (matching the existing tfact_problem_events full-refresh note) so it isn't missed. Addresses review feedback on #2411 from sentry[bot].
… coupons mitxpro b2b bulk-purchase coupons have a null coupon_id (see int__mitxpro__ecommerce_allcoupons), so every b2b row got source_discount_id = NULL. The new dedup CTE partitions by (platform_code, source_discount_id), and SQL groups all NULLs into one partition, so _row_num = 1 kept only a single b2b coupon and silently dropped the rest. Coalesce to b2bcoupon_id (negated to avoid colliding with the disjoint coupon_id numeric range) so each b2b coupon keeps a distinct source_discount_id.
blarghmatey
force-pushed
the
worktree-dbt-warehouse-audit
branch
from
July 16, 2026 15:28
0fe8271 to
6450936
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
dim_discount.discount_pkwas hashed from(source_discount_id, discount_code, platform_code), but the model docs andtfact_order's join both assume(source_discount_id, platform_code)is the unique grain.discount_codeis updated over its lifetime,dim_discountemitted multiple rows per(source_discount_id, platform_code), sotfact_order's dimension join on those two columns fanned out — and the final dedup intfact_orderpicked an arbitrarydiscount_fkbecauseorder_updated_onwas identical across the fanned rows.dim_discountto one row per(source_discount_id, platform_code), keeping the most recently updateddiscount_code, and hash the surrogate key from just those two columns to match the documented and consumed grain.discount_codeas a deterministic tie-breaker in the dedupROW_NUMBER()and an explicitdbt_utils.unique_combination_of_columnstest on(source_discount_id, platform_code)per review feedback.dim_discount.sqlandtfact_order'sdiscount_fkcolumn) that this surrogate-key change requires a--full-refreshoftfact_orderin the same deploy, sincedim_discountis full-refresh buttfact_orderis incremental and won't otherwise recomputediscount_fkfor historical rows.Test plan
dbt parseanddbt compile --select dim_discount tfact_ordersucceed against thedev_localduckdb targetpre-commit(sqlfluff, yamllint, etc.) passes on changed filesDeployment notes
dbt run --select tfact_order --full-refresh(or the equivalent full pipeline full-refresh) to avoid orphaneddiscount_fkvalues on historical order lines — see inline comments indim_discount.sql/_fact_tables.yml.Fixes #2379
🤖 Generated with Claude Code