← Back to Glossary

Bridge table

A bridge table resolves a many-to-many relationship between a fact table and a dimension (or between two dimensions) by holding pairs of keys, such as multiple salespeople credited on a single deal.

Overview

Star schemas assume each fact row relates to each dimension through a single, well-defined key — one customer, one product, one date. Some relationships are genuinely many-to-many, though: an order can have multiple salespeople credited to it, a bank account can have multiple joint owners, a patient can have multiple diagnoses on one visit. A bridge table (also called an associative or junction table) sits between the fact table and the dimension, holding the pairs of keys that make up the many-to-many relationship.

Example

Copy code

CREATE TABLE fact_deals ( deal_id INTEGER PRIMARY KEY, revenue DECIMAL(12,2) ); CREATE TABLE dim_salesperson ( salesperson_key INTEGER PRIMARY KEY, name VARCHAR ); -- Bridge table: one row per (deal, salesperson) pairing CREATE TABLE bridge_deal_salesperson ( deal_id INTEGER REFERENCES fact_deals(deal_id), salesperson_key INTEGER REFERENCES dim_salesperson(salesperson_key), allocation_pct DECIMAL(5,2), -- optional weighting to avoid double-counting PRIMARY KEY (deal_id, salesperson_key) ); -- Revenue split correctly across co-credited salespeople SELECT s.name, SUM(f.revenue * b.allocation_pct) AS attributed_revenue FROM fact_deals f JOIN bridge_deal_salesperson b ON b.deal_id = f.deal_id JOIN dim_salesperson s ON s.salesperson_key = b.salesperson_key GROUP BY ALL;

The double-counting trap

Joining a fact table straight through a bridge table without care will multiply rows: a $10,000 deal credited to two salespeople will appear twice, and a naive SUM(revenue) will double it to $20,000. The common fixes are an explicit weighting/allocation factor (as above, so shares sum to 1.0 per deal) or being deliberate that a query answering "total deal revenue" bypasses the bridge entirely, while a query answering "revenue by salesperson" goes through it and accepts the redistribution.

DuckDB angle

Bridge tables are ordinary tables and joins in DuckDB — nothing special is required — but it's worth validating with a quick SUM(allocation_pct) GROUP BY deal_id check that allocations actually sum to 1.0 per fact row before trusting attributed totals from a bridge-table join.

Related terms

FAQS

By including a weighting or allocation column (e.g., a percentage that sums to 1.0 across all rows for a given fact) so that measures split across multiple related dimension rows, rather than being duplicated once per relationship.