pbPassingBI
/
Data modeling advanced 10 min

Relationships and filter direction

Cardinality, cross-filter direction, and the ambiguity traps.

What you'll be able to do
  • Set cardinality and cross-filter direction deliberately
  • Explain why bidirectional filtering is risky
  • Handle inactive relationships with USERELATIONSHIP

Cardinality

One-to-many is the normal case: one row in the dimension, many in the fact. Filters flow from the one side to the many side automatically.

Many-to-one is the same thing described from the other end. One-to-one is rare and usually means two tables should be merged. Many-to-many is supported directly now, but it introduces ambiguity and is usually a sign a bridge table would be cleaner.

Cross-filter direction

Single (the default and the right answer nearly always) means filters flow one way: dimension filters fact, never the reverse.

Both makes filters flow in both directions. It's tempting — it makes a slicer built on one table filter another — but it creates ambiguous paths in a model with several fact tables, and the engine may resolve them in ways you don't expect. It can also cause circular dependency errors.

When you need the effect of bidirectional filtering in one specific measure, use CROSSFILTER inside CALCULATE instead of changing the model globally. Local, explicit, and doesn't break anything else.

Active and inactive relationships

Only one active relationship can exist between two tables along a given path. A Sales table with OrderDate, ShipDate, and DueDate can only have one active join to Date; the others are created as inactive (dashed line).

Activate one for a specific measure with USERELATIONSHIP:

Shipped Amount =
CALCULATE(
    SUM(Sales[Amount]),
    USERELATIONSHIP(Sales[ShipDate], 'Date'[Date])
)

This is far better than duplicating the Date table — you keep one dimension and one set of slicers.

Role-playing dimensions

That Sales-to-Date example is a role-playing dimension: one dimension used in several roles. USERELATIONSHIP is the idiomatic Power BI answer.

The alternative — importing Date three times as OrderDate, ShipDate, DueDate — is sometimes clearer for self-service users who want three separate slicers, but it multiplies maintenance. Pick one approach and be consistent.

Key points
  • Filters flow from the one side to the many side by default
  • Prefer single direction; use CROSSFILTER in a measure instead of Both
  • USERELATIONSHIP activates an inactive relationship for one calculation
Check yourself