Reconciliation Summary
- Base rows: match (both 20,725,661)
- Level 1 rows: match (both 1,091,811)
-
Level 2 rows: Notebook has +232 rows because it groups by two extra
columns the SQL views don't:
PurchaseOrderNumberintroduces +117 rowsInternalVendorNameintroduces +115 rows
- Level 2 SUM: match within 0.00007% (£44k on £63bn) — residual difference is due to moving data in prod between the two measurements, not a logic gap
- Notebook Final SUM: equals Notebook Level 2 SUM exactly (pure GROUP BY pass-through, no data lost)
- SQL Final SUM: comes from a static physical table refreshed on ETL schedule; use SQL Live Level 2 as the reference for Notebook Final
Fixes applied
- Base view (
df_vwprojpostedtranstable): addedrecid IS NOT NULLto the filter, removed.distinct() - Final table (
legacy.vwfactsubcontractorinvoicing_pmsummary_nonpo): removedDISTINCTfrom the CTE and outer SELECT (recovered £1.07bn)
Layer-by-layer reconciliation
| Layer | Metric | SQL Views | Notebook | Diff (NB − Duf) | % Diff | Balance |
|---|---|---|---|---|---|---|
| Base | Rows | 20,725,661 | 20,725,661 | 0 | 0.00000% | Match |
| Fact | Rows | 1,091,811 | 1,091,811 | 0 | 0.00000% | Match |
| Level 2 | Rows | 166,164 | 166,396 | +232 | +0.13962% | Amounts Matched |
| Level 2 | SUM | 62,948,788,740.34 | 62,948,744,322.29 | −44,418.05 | −0.00007% | Match (drift) |
| Final | SUM | 62,947,556,151.27 STATIC | 62,948,744,322.29 LIVE | +1,188,171.02 | +0.00189% | SQL Final stale |
| Final | SUM (vs SQL Live Level 2) |
62,948,788,740.34 LIVE | 62,948,744,322.29 LIVE | −44,418.05 | −0.00007% | Match (drift) |
LIVE reads through to bronze each query.
STATIC reads from
[DW].[tblVwFactSubContractorInvoicing_Customer], refreshed on ETL schedule.
Notebook Final is a pure pass-through of Notebook Level 2
| Notebook table | SUM(AccountingSubconInvoiceAmount) |
|---|---|
| legacy.vwfactsubcontractorinvoicing_subcon | 62,948,744,322.288660 |
| legacy.vwfactsubcontractorinvoicing_pmsummary_nonpo | 62,948,744,322.288660 |
| Diff | 0.000000 |
Fixes applied
-
Cell 35
Base — align WHERE filter with SQL Views
Addedcol("recid").isNotNull()to the filter and removed.distinct(). Matches the SQL view's(recid IS NOT NULL OR recid <> 0) AND IsDelete IS NULL.Creates notebook temp viewdf_vwprojpostedtranstable| equivalent of SQL view[ax].[vwPROJPOSTEDTRANSTABLE].filter( col("IsDelete").isNull() & col("recid").isNotNull() )Base row count balanced at 20,725,661 -
Cell 147
Final — remove DISTINCT from pmsummary_nonpo CTE and outer SELECT
TheWITH a AS (SELECT DISTINCT ...)block at the top of pmsummary_nonpo included the amount columns in itsDISTINCT, and droppedVendorKey,ProjectCategoryKey,InternalVendorName,SubConInvoiceDate, andCustomerInvoiceDatefrom the projection. Any two Level 2 rows that shared identical values across the selected columns (including the amounts) but differed on one of the dropped columns were collapsed into a single row, silently losing the second row's amount contribution. The outerGROUP BYalready aggregates to the correct grain on its own, so theDISTINCTwas both redundant and destructive.Creates notebook delta tablelegacy.vwfactsubcontractorinvoicing_pmsummary_nonpo| equivalent of SQL view[TNTCore].[VwFactSubContractorInvoicing_Customer]WITH a AS ( SELECT -- was: SELECT DISTINCT sc.ProjectKey, ..., sc.PurchaseOrderNumber, SubConRevenue, ..., AccountingSubconInvoiceAmount, ... FROM subcon sc ) SELECT -- was: SELECT DISTINCT ProjectKey, ..., SUM(AccountingSubconInvoiceAmount), ... FROM a GROUP BY ProjectKey, ...Recovered £1,075,252,864.39 — Final SUM went from 61,873,491,457.90 to 62,948,744,322.29