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.