Implement and Manage Semantic Models · Topic 2 of 6
Model Star Schema and Relationships
Implement a star schema in a semantic model: relationship cardinality, filter direction, role-playing dates, bridge tables and many-to-many relationships.
- 5 min
- Dimensions filter facts through one-to-many relationships with single direction by default.
- Only one active relationship between two tables; use
USERELATIONSHIPfor the inactive ones. - Bridge tables resolve many-to-many between two dimensions; filters need Both or
CROSSFILTERto pass through.
What it is
In a semantic model, a star schema is a set of tables joined by relationships. Filters flow along those relationships, from a dimension such as Product to a fact table such as Sales, and that flow is what makes a measure show the right number in every cell.
Most relationships are simple one-to-many links. The exam focuses on the harder cases: dimensions used in several roles, bridge tables and many-to-many relationships.
How it works
Relationship properties
| Property | Options | Guidance |
|---|---|---|
| Cardinality | One-to-many, one-to-one, many-to-many | Dimension (one) to fact (many) is the norm |
| Cross-filter direction | Single or Both | Single by default; Both only where needed |
| Active | Active or inactive | Only one active path between two tables |
| Assume referential integrity | On or off | DirectQuery only; uses inner joins for faster queries |
Good star schema habits in the model: hide fact table key columns, mark a dedicated date table with Mark as date table, and turn off Auto date/time, which creates a hidden date table for every date column.
Role-playing dimensions
A Sales table may have OrderDateKey and ShipDateKey, both pointing to the same Date table. Only one relationship can be active; the other is inactive. A measure activates it with USERELATIONSHIP:
Sales by Ship Date =
CALCULATE (
[Total Sales],
USERELATIONSHIP ( Sales[ShipDateKey], 'Date'[DateKey] )
)
The alternative is to load the Date table twice, as Order Date and Ship Date. That lets users slice by both at once without special measures, at the cost of a second table.
Bridge tables
A bank customer can hold several accounts, and a joint account has several customers. Neither table can sit on the one side, so a bridge table lists every customer and account pair.
A filter on Customer reaches the bridge, but by default it does not continue from the bridge to Account, because that relationship filters the other way. You have two options:
- Set the Account to CustomerAccount relationship to Both, so the bridge filters Account.
- Keep it Single and enable the direction only inside the measures that need it, with
CROSSFILTER:
Customer Balance =
CALCULATE (
SUM ( Transactions[Amount] ),
CROSSFILTER ( CustomerAccount[AccountID], Account[AccountID], Both )
)
Expect non-additive totals: a joint account is counted under each of its customers, but only once in the grand total.
Many-to-many cardinality
A sales target table stored by Category and month cannot relate one-to-many to the Product table, because Category repeats in both tables. A many-to-many cardinality relationship on the Category column joins them directly. It is a limited relationship, so unmatched keys do not get a blank row.
When the relationship should exist only for one calculation, a virtual relationship with TREATAS does the same job without changing the model:
Target Amount =
CALCULATE (
SUM ( Targets[Amount] ),
TREATAS ( VALUES ( 'Product'[Category] ), Targets[Category] )
)
Why Both is used sparingly
Bidirectional filters can create ambiguous paths when two routes connect the same tables, which Power BI refuses or resolves in ways users do not expect. They also make queries slower because more tables are filtered. Use them on bridge relationships, not as a default.
A worked example
An insurer models policies, customers and claims. A policy can have several named customers.
- Fact table
Claimsrelates many-to-one toPolicy. - Bridge table
PolicyCustomerholds one row per policy and customer pair, related to bothPolicyandCustomer. - Analysts filter claims by customer, so the
PolicytoPolicyCustomerrelationship is set to Both; all other relationships stay Single. - Claims have
ClaimDateandReportedDate.ClaimDateis active, and aClaims by Reported Datemeasure usesUSERELATIONSHIPfor the other.
When a question says "one item belongs to many groups and each group has many items", the expected design is a bridge table with a bidirectional filter on one relationship, or CROSSFILTER in the measure.
How the exam asks about this
- "Report sales by order date and by ship date with one Date table." An inactive relationship plus
USERELATIONSHIPin a measure. - "Customers share accounts; filter transactions by customer." A bridge table with the bridge to Account direction set to Both, or
CROSSFILTER. - "Relate targets at category grain to a product-level model." A many-to-many relationship on Category, or
TREATASin the measure.
What to remember for the exam
- Dimensions filter facts through one-to-many relationships with single direction by default.
- Only one active relationship between two tables; use
USERELATIONSHIPfor the inactive ones. - Bridge tables resolve many-to-many between two dimensions; filters need Both or
CROSSFILTERto pass through. - Many-to-many cardinality relates tables at different grains; it is a limited relationship.
TREATASapplies the values of one column as a filter on another, like a virtual relationship.
Setting every relationship to Both does not fix many-to-many problems. It causes ambiguous paths and slow queries. Enable Both only on the bridge relationship that needs it.
Common mistakes
Joining two dimension tables directly. That creates a snowflake and often an ambiguous path. Flatten the dimensions or relate each to the fact table.
Expecting totals to add up in a bridge design. Shared items are counted once per related member but once in the total, which is correct many-to-many behaviour.
Using Auto date/time in an enterprise model. It adds a hidden table per date column and bloats the model. Use one marked date table.
Check yourself
How does a measure use an inactive relationship?
It wraps the calculation in
CALCULATEwithUSERELATIONSHIPnaming the two related columns.Why does a filter on Customer not reach Account through a bridge table by default?
The Account to bridge relationship filters from Account to the bridge only. Set it to Both or use
CROSSFILTERin the measure.When do you use a many-to-many cardinality relationship?
When neither column is unique, such as targets stored by Category related to a Product table where Category repeats.
Topic 2 of 6 in Implement and Manage Semantic Models
Test yourself on Implement and Manage Semantic Models
The full Microsoft DP-600 question bank has 648 questions, with timed practice exams and an explanation for every answer.
This study guide is independent and is not affiliated with, endorsed by, or sponsored by Microsoft. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.