diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-1.png b/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-1.png deleted file mode 100644 index 3b4ef14fc9..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-1.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-1.svg b/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-1.svg new file mode 100644 index 0000000000..f455b8f313 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-1.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-2.png b/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-2.png deleted file mode 100644 index 6bc5a33718..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-2.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-2.svg b/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-2.svg new file mode 100644 index 0000000000..39f2812cee --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-active-inactive/flight-model-2.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/flight-report-design.png b/powerbi-docs/guidance/media/relationships-active-inactive/flight-report-design.png deleted file mode 100644 index 3cd4e327fe..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-active-inactive/flight-report-design.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/flight-report-design.svg b/powerbi-docs/guidance/media/relationships-active-inactive/flight-report-design.svg new file mode 100644 index 0000000000..b5aefe6181 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-active-inactive/flight-report-design.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/sales-model.png b/powerbi-docs/guidance/media/relationships-active-inactive/sales-model.png deleted file mode 100644 index e84669c105..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-active-inactive/sales-model.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/sales-model.svg b/powerbi-docs/guidance/media/relationships-active-inactive/sales-model.svg new file mode 100644 index 0000000000..316a65b6ca --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-active-inactive/sales-model.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/sales-report-design.png b/powerbi-docs/guidance/media/relationships-active-inactive/sales-report-design.png deleted file mode 100644 index 9e10ca71c7..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-active-inactive/sales-report-design.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-active-inactive/sales-report-design.svg b/powerbi-docs/guidance/media/relationships-active-inactive/sales-report-design.svg new file mode 100644 index 0000000000..fe84301314 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-active-inactive/sales-report-design.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/country-sales-crossfilter-function.png b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/country-sales-crossfilter-function.png deleted file mode 100644 index f984478746..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/country-sales-crossfilter-function.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/country-sales-crossfilter-function.svg b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/country-sales-crossfilter-function.svg new file mode 100644 index 0000000000..2f8929f074 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/country-sales-crossfilter-function.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/filter-product-slicer-measure-is-not-blank.png b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/filter-product-slicer-measure-is-not-blank.png deleted file mode 100644 index fd320529c0..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/filter-product-slicer-measure-is-not-blank.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/filter-product-slicer-measure-is-not-blank.svg b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/filter-product-slicer-measure-is-not-blank.svg new file mode 100644 index 0000000000..45d1dc5c74 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/filter-product-slicer-measure-is-not-blank.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows-bi-directional-filter.png b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows-bi-directional-filter.png deleted file mode 100644 index 0618674f2f..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows-bi-directional-filter.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows-bi-directional-filter.svg b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows-bi-directional-filter.svg new file mode 100644 index 0000000000..ce5072ae10 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows-bi-directional-filter.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows.png b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows.png deleted file mode 100644 index f50c6adb4f..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows.svg b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows.svg new file mode 100644 index 0000000000..06bf00a3a3 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram-rows.svg @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram.png b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram.png deleted file mode 100644 index a3b0f13ce9..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram.svg b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram.svg new file mode 100644 index 0000000000..f02b3d016b --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-model-diagram.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-bi-directional-filter.png b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-bi-directional-filter.png deleted file mode 100644 index 18d5c78cb5..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-bi-directional-filter.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-bi-directional-filter.svg b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-bi-directional-filter.svg new file mode 100644 index 0000000000..19424d42c6 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-bi-directional-filter.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-no-bi-directional-filter.png b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-no-bi-directional-filter.png deleted file mode 100644 index 0168af0db0..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-no-bi-directional-filter.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-no-bi-directional-filter.svg b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-no-bi-directional-filter.svg new file mode 100644 index 0000000000..54904159ae --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-bidirectional-filtering/sales-report-no-bi-directional-filter.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-example.png b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-example.png deleted file mode 100644 index 9d45068323..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-example.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-example.svg b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-example.svg new file mode 100644 index 0000000000..31f56baf70 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-example.svg @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-1.png b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-1.png deleted file mode 100644 index c07e9a114a..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-1.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-1.svg b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-1.svg new file mode 100644 index 0000000000..fc41c6ab8a --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-1.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-2.png b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-2.png deleted file mode 100644 index 73534fa923..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-2.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-2.svg b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-2.svg new file mode 100644 index 0000000000..e8953942b3 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-queried-2.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-1.png b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-1.png deleted file mode 100644 index f03cccd31d..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-1.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-1.svg b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-1.svg new file mode 100644 index 0000000000..64448abf23 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-1.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-2.png b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-2.png deleted file mode 100644 index dfd975b385..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-2.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-2.svg b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-2.svg new file mode 100644 index 0000000000..c744dfa61d --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-2.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-3.png b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-3.png deleted file mode 100644 index c3de44425c..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-3.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-3.svg b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-3.svg new file mode 100644 index 0000000000..c35d3ec4d8 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/bank-account-customer-model-related-tables-3.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-example.png b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-example.png deleted file mode 100644 index 9a2ffc0c95..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-example.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-example.svg b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-example.svg new file mode 100644 index 0000000000..f13ab1e7c1 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-example.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-improved.png b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-improved.png deleted file mode 100644 index 5022d6a210..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-improved.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-improved.svg b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-improved.svg new file mode 100644 index 0000000000..e95a0a69e5 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-improved.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-queried.png b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-queried.png deleted file mode 100644 index 5dd7a47d39..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-queried.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-queried.svg b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-queried.svg new file mode 100644 index 0000000000..0e0b747c88 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-queried.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-related-tables.png b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-related-tables.png deleted file mode 100644 index 3b5acd8917..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-related-tables.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-related-tables.svg b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-related-tables.svg new file mode 100644 index 0000000000..abaef2ceea --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/order-fulfillment-model-related-tables.svg @@ -0,0 +1,603 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example-final.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example-final.png deleted file mode 100644 index c754f014ab..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example-final.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example-final.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example-final.svg new file mode 100644 index 0000000000..765274f2f9 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example-final.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example.png deleted file mode 100644 index 69bd73cb9f..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example.svg new file mode 100644 index 0000000000..c1f4bd7d2f --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-example.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-bad.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-bad.png deleted file mode 100644 index 705230492e..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-bad.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-bad.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-bad.svg new file mode 100644 index 0000000000..49aab403bf --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-bad.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-good.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-good.png deleted file mode 100644 index d4ad973a80..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-good.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-good.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-good.svg new file mode 100644 index 0000000000..d89371a99e --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-matrix-blank-months-good.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date-tables.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date-tables.png deleted file mode 100644 index 5270a88e08..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date-tables.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date-tables.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date-tables.svg new file mode 100644 index 0000000000..d9bc2573c0 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date-tables.svg @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date.png deleted file mode 100644 index f2dddebd23..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date.svg new file mode 100644 index 0000000000..f1fbea7792 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-relate-non-date.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-target-rows.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-target-rows.png deleted file mode 100644 index cbc57609de..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-target-rows.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-target-rows.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-target-rows.svg new file mode 100644 index 0000000000..c6c1a9dd4d --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-target-rows.svg @@ -0,0 +1,595 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-category-targets.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-category-targets.png deleted file mode 100644 index 424b60cb8b..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-category-targets.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-bad.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-bad.png deleted file mode 100644 index cde9ad04b8..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-bad.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-bad.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-bad.svg new file mode 100644 index 0000000000..8de8938567 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-bad.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-good.png b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-good.png deleted file mode 100644 index 8cfd5cc6ee..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-good.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-good.svg b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-good.svg new file mode 100644 index 0000000000..13d518bde9 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-many-to-many/sales-targets-model-visual-color-targets-good.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-2.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-2.png deleted file mode 100644 index 6530bfc560..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-2.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-2.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-2.svg new file mode 100644 index 0000000000..0ca6a30f53 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-2.svg @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consequences.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consequences.svg new file mode 100644 index 0000000000..8d859525c6 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consequences.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consolidated-consequences.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consolidated-consequences.svg new file mode 100644 index 0000000000..350def2a79 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consolidated-consequences.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consolidated.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consolidated.svg new file mode 100644 index 0000000000..b7132f1fd3 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-consolidated.svg @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-cross-source.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-cross-source.svg new file mode 100644 index 0000000000..6a6caf2466 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-cross-source.svg @@ -0,0 +1,299 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-display-folder.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-display-folder.png deleted file mode 100644 index 8c9d3351bb..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-display-folder.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-into-display-folder.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-into-display-folder.svg new file mode 100644 index 0000000000..6cf5c77429 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-into-display-folder.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-with-hierarchy.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-with-hierarchy.png deleted file mode 100644 index dca51a7486..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-with-hierarchy.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-with-hierarchy.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-with-hierarchy.svg new file mode 100644 index 0000000000..1349d1ae4a --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-with-hierarchy.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated.png deleted file mode 100644 index 44740ef973..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane-consolidated.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane.png deleted file mode 100644 index 84b8a7d27b..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-data-pane.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-null-replaced.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-null-replaced.png deleted file mode 100644 index 645724dda2..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-null-replaced.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-weak-relationship.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-weak-relationship.png deleted file mode 100644 index 156d1e8814..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-weak-relationship.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-weak-relationship.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-weak-relationship.svg new file mode 100644 index 0000000000..e04bee8cd3 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual-weak-relationship.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual.png deleted file mode 100644 index 09e0fc4997..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category-table-visual.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category.png b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category.png deleted file mode 100644 index 176e0fe4e6..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category.svg b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category.svg new file mode 100644 index 0000000000..879c3c86e1 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/product-to-product-category.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-degenerate.png b/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-degenerate.png deleted file mode 100644 index 6b84021b61..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-degenerate.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-degenerate.svg b/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-degenerate.svg new file mode 100644 index 0000000000..1cd3841b20 --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-degenerate.svg @@ -0,0 +1,458 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-rows.png b/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-rows.png deleted file mode 100644 index 78ab355979..0000000000 Binary files a/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-rows.png and /dev/null differ diff --git a/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-rows.svg b/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-rows.svg new file mode 100644 index 0000000000..553b2161ad --- /dev/null +++ b/powerbi-docs/guidance/media/relationships-one-to-one/sales-order-rows.svg @@ -0,0 +1,448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/powerbi-docs/guidance/relationships-active-inactive.md b/powerbi-docs/guidance/relationships-active-inactive.md index 7d3d301832..73ce465247 100644 --- a/powerbi-docs/guidance/relationships-active-inactive.md +++ b/powerbi-docs/guidance/relationships-active-inactive.md @@ -1,6 +1,6 @@ --- title: "Active vs inactive relationship guidance" -description: Guidance for using active or inactive model relationships. +description: "Guidance for using active or inactive model relationships." author: denglishbi ms.author: daengli ms.reviewer: maroche @@ -8,93 +8,93 @@ ms.service: powerbi ms.subservice: powerbi-resource ms.topic: conceptual ms.custom: fabric-cat -ms.date: 05/04/2023 +ms.date: 12/27/2024 --- # Active vs inactive relationship guidance -This article targets you as a data modeler working with Power BI Desktop. It provides you with guidance on when to create active or inactive model relationships. By default, active relationships propagate filters to other tables. Inactive relationship, however, only propagate filters when a DAX expression activates (uses) the relationship. +This article targets you as a data modeler who works with Power BI Desktop. It provides you with guidance on when to create active or inactive model relationships. By default, active relationships propagate filters to other tables. Inactive relationship, however, only propagate filters when a DAX expression activates (uses) the relationship. [!INCLUDE [relationships-prerequisite-reading](includes/relationships-prerequisite-reading.md)] ## Active relationships -Generally, we recommend defining active relationships whenever possible. They widen the scope and potential of how your model can be used by report authors, and users working with Q&A. +Generally, we recommend that you define active relationships whenever possible. They widen the scope and potential of how your model can be used by report authors, and users working with Q&A. -Consider an example of an Import model designed to analyze airline flight on-time performance (OTP). The model has a **Flight** table, which is a fact-type table storing one row per flight. Each row records the flight date, flight number, departure and arrival airports, and any delay time (in minutes). There's also an **Airport** table, which is a dimension-type table storing one row per airport. Each row describes the airport code, airport name, and the country or region. +Consider an example of an [Import model](../connect-data/service-dataset-modes-understand.md#import-mode) designed to analyze airline flight on-time performance (OTP). The model has a `Flight` table, which is a [fact table](star-schema.md#fact-tables) that stores one row per flight. Each row records the flight date, flight number, departure and arrival airports, and any delay time (in minutes). There's also an `Airport` table, which is a [dimension table](star-schema.md#dimension-tables) that stores one row per airport. Each row describes the airport code, airport name, and the country or region. Here's a partial model diagram of the two tables. -![Diagram showing a model containing two tables: Flight and Airport. The relationship design is described in the following paragraph.](media/relationships-active-inactive/flight-model-1.png) +:::image type="content" source="media/relationships-active-inactive/flight-model-1.svg" alt-text="Diagram showing a model containing two tables: Flight and Airport. The relationship design is described in the following paragraph." border="false"::: -There are two model relationships between the **Flight** and **Airport** tables. In the **Flight** table, the **DepartureAirport** and **ArrivalAirport** columns relate to the **Airport** column of the **Airport** table. In star schema design, the **Airport** table is described as a [role-playing dimension](star-schema.md#role-playing-dimensions). In this model, the two roles are _departure airport_ and _arrival airport_. +There are two model relationships between the `Flight` and `Airport` tables. In the `Flight` table, the `DepartureAirport` and `ArrivalAirport` columns relate to the `Airport` column of the `Airport` table. In star schema design, the `Airport` table is described as a [role-playing dimension](star-schema.md#role-playing-dimensions). In this model, the two roles are _departure airport_ and _arrival airport_. -While this design works well for relational star schema designs, it doesn't for Power BI models. It's because model relationships are paths for filter propagation, and these paths must be deterministic. For more information on ensuring that filter propagation paths are deterministic see [resolve relationship path ambiguity](../transform-model/desktop-relationships-understand.md#resolve-relationship-path-ambiguity).Therefore—as described in this example—one relationship is active while the other is inactive (represented by the dashed line). Specifically, it's the relationship to the **ArrivalAirport** column that's active. This means filters applied to the **Airport** table automatically propagate to the **ArrivalAirport** column of the **Flight** table. +While this design works well for relational star schema designs, it doesn't work well for Power BI models. That's because model relationships are paths for filter propagation, and these paths must be deterministic. For more information on ensuring that filter propagation paths are deterministic see [resolve relationship path ambiguity](../transform-model/desktop-relationships-understand.md#resolve-relationship-path-ambiguity).Therefore—as presented in this example—one relationship is active while the other is inactive (represented by the dashed line). Specifically, it's the relationship to the `ArrivalAirport` column that's active, which means filters applied to the `Airport` table automatically propagate to the `ArrivalAirport` column of the `Flight` table. -This model design imposes severe limitations on how the data can be reported. Specifically, it's not possible to filter the **Airport** table to automatically isolate flight details for a departure airport. As reporting requirements involve filtering (or grouping) by departure and arrival airports _at the same time_, two active relationships are needed. Translating this requirement into a Power BI model design means the model must have two airport tables. +This model design imposes severe limitations on how the data can be reported. Specifically, it's not possible to filter the `Airport` table to automatically isolate flight details for a departure airport. As reports need to filter (or group) by departure and arrival airports _at the same time_, two active relationships are required. Translating this requirement into a Power BI model design means the model must have two airport tables. Here's the improved model design. -![Diagram showing a model containing four tables: Date, Flight, Departure Airport, and Arrival Airport.](media/relationships-active-inactive/flight-model-2.png) +:::image type="content" source="media/relationships-active-inactive/flight-model-2.svg" alt-text="Diagram showing a model containing four tables: Date, Flight, Departure Airport, and Arrival Airport." border="false"::: -The model now has two airport tables: **Departure Airport** and **Arrival Airport**. The model relationships between these tables and the **Flight** table are active. Notice also that the column names in the **Departure Airport** and **Arrival Airport** tables are prefixed with the word _Departure_ or _Arrival_. +The model now has two airport tables: `Departure Airport` and `Arrival Airport`. Each model relationship between these tables and the `Flight` table is active. Notice also that the column names in the `Departure Airport` and `Arrival Airport` tables are prefixed with the word _Departure_ or _Arrival_. The improved model design supports producing the following report design. -![Diagram showing a report page has two slicers and a table visual. The slicers are Month and Departure Airport.](media/relationships-active-inactive/flight-report-design.png) +:::image type="content" source="media/relationships-active-inactive/flight-report-design.svg" alt-text="Diagram showing a report page has two slicers and a table visual. The slicers are Month and Departure Airport." border="false"::: -The report page filters by Melbourne as the departure airport, and the table visual groups by arrival airports. +The report page filters by **Melbourne** as the departure airport, and the table visual groups by arrival airports. > [!NOTE] -> For Import models, the additional table has resulted in an increased model size, and longer refresh times. As such, it contradicts the recommendations described in the [Data reduction techniques for Import modeling](import-modeling-data-reduction.md) article. However, in the example, the requirement to have only active relationships overrides these recommendations. +> For Import models, the addition of another dimension table has resulted in an increased model size, and longer refresh times. As such, it contradicts the recommendations described in the [Data reduction techniques for Import modeling](import-modeling-data-reduction.md) article. However, in the example, the requirement to have only active relationships overrides these recommendations. > -> Further, it's common that dimension-type tables contain low row counts relative to fact-type table row counts. So, the increased model size and refresh times aren't likely to be excessively large. +> Further, it's common that dimension tables store low row counts relative to fact table row counts. So, the increased model size and refresh times aren't likely to be excessively large. ### Refactoring methodology -Here's a methodology to refactor a model from a single role-playing dimension-type table, to a design with _one table per role_. +Here's a methodology to refactor a model from a single role-playing dimension table, to a design with _one table per role_. 1. Remove any inactive relationships. -2. Consider renaming the role-playing dimension-type table to better describe its role. In the example, the **Airport** table is related to the **ArrivalAirport** column of the **Flight** table, so it's renamed as **Arrival Airport**. -3. Create a copy of the role-playing table, providing it with a name that reflects its role. If it's an Import table, we recommend defining a calculated table. If it's a DirectQuery table, you can duplicate the Power Query query. +1. Consider renaming the role-playing dimension table to better describe its role. In the example in this article, the `Airport` table is related to the `ArrivalAirport` column of the `Flight` table, so it's renamed as `Arrival Airport`. +1. Create a copy of the role-playing table, providing it with a name that reflects its role. If it's an Import table, we recommend you create a calculated table. If it's a DirectQuery table, you can duplicate the Power Query query. - In the example, the **Departure Airport** table was created by using the following calculated table definition. + In the example, the `Departure Airport` table was created by using the following calculated table definition. ```dax Departure Airport = 'Arrival Airport' ``` -4. Create an active relationship to relate the new table. -5. Consider renaming the columns in the tables so they accurately reflect their role. In the example, all columns are prefixed with the word _Departure_ or _Arrival_. These names ensure report visuals, by default, will have self-describing and non-ambiguous labels. It also improves the Q&A experience, allowing users to easily write their questions. -6. Consider adding descriptions to role-playing tables. (In the **Fields** pane, a description appears in a tooltip when a report author hovers their cursor over the table.) This way, you can communicate any additional filter propagation details to your report authors. +1. Create an active relationship to relate the new table. +1. Consider renaming the columns in the tables so they accurately reflect their role. In the example in this article, all columns are prefixed with the word _Departure_ or _Arrival_. These names ensure report visuals, by default, will have self-describing and non-ambiguous labels. It also improves the Q&A experience, allowing users to easily write accurate questions. +1. Consider adding descriptions to role-playing tables. (In the **Data** pane, a description appears in a tooltip when a report author hovers their cursor over the table.) This way, you can communicate other filter propagation details to report authors. ## Inactive relationships -In specific circumstances, inactive relationships can address special reporting needs. +In specific circumstances, inactive relationships can address specific reporting needs. -Let's now consider different model and reporting requirements: +Consider different model and reporting requirements: -- A sales model contains a **Sales** table that has two date columns: **OrderDate** and **ShipDate** -- Each row in the **Sales** table records a single order -- Date filters are almost always applied to the **OrderDate** column, which always stores a valid date -- Only one measure requires date filter propagation to the **ShipDate** column, which can contain BLANKs (until the order is shipped) -- There's no requirement to simultaneously filter (or group by) order _and_ ship date periods +- A sales model contains a `Sales` table that has two date columns: `OrderDate` and `ShipDate`. +- Each row in the `Sales` table records a single order. +- Date filters are almost always applied to the `OrderDate` column, which always stores a valid date. +- Only one measure requires date filter propagation to the `ShipDate` column, which can contain BLANKs (until the order is shipped). +- There's no requirement to simultaneously filter (or group) order _and_ ship date periods. Here's a partial model diagram of the two tables. -![Diagram showing a model containing two tables: Sales and Date. The Sales table includes six measures.](media/relationships-active-inactive/sales-model.png) +:::image type="content" source="media/relationships-active-inactive/sales-model.svg" alt-text="Diagram showing a model containing two tables: Sales and Date. The Sales table includes six measures." border="false"::: -There are two model relationships between the **Sales** and **Date** tables. In the **Sales** table, the **OrderDate** and **ShipDate** columns relate to the **Date** column of the **Date** table. In this model, the two roles for the **Date** table are _order date_ and _ship date_. It's the relationship to the **OrderDate** column that's active. +There are two model relationships between the `Sales` and `Date` tables. In the `Sales` table, the `OrderDate` and `ShipDate` columns relate to the `Date` column of the `Date` table. In this model, the two roles for the `Date` table are _order date_ and _ship date_. It's the relationship to the `OrderDate` column that's active. -All of the six measures—except one—must filter by the **OrderDate** column. The **Orders Shipped** measure, however, must filter by the **ShipDate** column. +All of the six measures—except one—must filter by the `OrderDate` column. The `Orders Shipped` measure, however, must filter by the `ShipDate` column. -Here's the **Orders** measure definition. It simply counts the rows of the **Sales** table within the filter context. Any filters applied to the **Date** table will propagate to the **OrderDate** column. +Here's the `Orders` measure definition. It simply counts the rows of the `Sales` table within the filter context. Any filters applied to the `Date` table propagate to the `OrderDate` column. ```dax Orders = COUNTROWS(Sales) ``` -Here's the **Orders Shipped** measure definition. It uses the [USERELATIONSHIP](/dax/userelationship-function-dax) DAX function, which activates filter propagation for a specific relationship only during the evaluation of the expression. In this example, the relationship to the **ShipDate** column is used. +Here's the `Orders Shipped` measure definition. It uses the [USERELATIONSHIP](/dax/userelationship-function-dax) DAX function, which activates filter propagation for a specific relationship, but only during the evaluation of the expression. In this example, the relationship to the `ShipDate` column is used. ```dax Orders Shipped = @@ -106,23 +106,23 @@ CALCULATE( This model design supports producing the following report design. -![Diagram showing a report page with one slicer and a table visual. The slicer is Quarter, and the table visual lists monthly sales statistics.](media/relationships-active-inactive/sales-report-design.png) +:::image type="content" source="media/relationships-active-inactive/sales-report-design.svg" alt-text="Diagram showing a report page with one slicer and a table visual. The slicer is Quarter, and the table visual lists monthly sales statistics." border="false"::: -The report page filters by quarter 2019 Q4. The table visual groups by month and displays various sales statistics. The **Orders** and **Orders Shipped** measures produce different results. They each use the same summarization logic (count rows of the **Sales** table), but different **Date** table filter propagation. +The report page filters by quarter **2019 Q4**. The table visual groups by month and displays various sales statistics. The `Orders` and `Orders Shipped` measures produce different results. They each use the same summarization logic (count rows of the `Sales` table), but different `Date` table filter propagation. -Notice that the quarter slicer includes a BLANK item. This slicer item appears as a result of [table expansion](../transform-model/desktop-relationships-understand.md#regular-relationships). While each **Sales** table row has an order date, some rows have a BLANK ship date—these orders are yet to be shipped. Table expansion considers inactive relationships too, and so BLANKs can appear due to BLANKs on the many-side of the relationship, or due to data integrity issues. +Notice that the quarter slicer includes a BLANK option. This slicer option appears as a result of [table expansion](../transform-model/desktop-relationships-understand.md#regular-relationships). While each `Sales` table row has a valid order date, some rows have a BLANK ship date—these orders are yet to be shipped. Table expansion considers inactive relationships too, and so BLANKs can appear due to BLANKs on the many-side of the relationship (or due to data integrity issues). > [!NOTE] -> Row-level security filters only propagate through active relationships. Row-level security filters will not propagate for inactive relationships even if UseRelationship is added explicitly to a measure definition. +> Row-level security (RLS) filters only propagate through active relationships. RLS filters never propagate for inactive relationships, even when the [USERELATIONSHIP](/dax/userelationship-function-dax) DAX function is used by a measure definition. ## Recommendations -In summary, we recommend defining active relationships whenever possible, especially when row-level security roles are defined for your data model. They widen the scope and potential of how your model can be used by report authors, and users working with Q&A. It means that role-playing dimension-type tables should be duplicated in your model. +We recommend that you define active relationships whenever possible, especially when RLS roles are defined for your data model. They widen the scope and potential of how your model can be used by report authors, and users working with Q&A. It means that role-playing dimension tables should be duplicated in your model. -In specific circumstances, however, you can define one or more inactive relationships for a role-playing dimension-type table. You can consider this design when: +In specific circumstances, however, you can define one or more inactive relationships for a role-playing dimension table. You can consider this approach when: -- There's no requirement for report visuals to simultaneously filter by different roles -- You use the USERELATIONSHIP DAX function to activate a specific relationship for relevant model calculations +- There's no requirement for report visuals to simultaneously filter by different roles. +- You use the USERELATIONSHIP DAX function to activate a specific relationship for relevant model calculations. ## Related content @@ -131,5 +131,5 @@ For more information related to this article, check out the following resources: - [Model relationships in Power BI Desktop](../transform-model/desktop-relationships-understand.md) - [Understand star schema and the importance for Power BI](star-schema.md) - [Relationship troubleshooting guidance](relationships-troubleshoot.md) -- Questions? [Try asking the Power BI Community](https://community.powerbi.com/) -- Suggestions? [Contribute ideas to improve Power BI](https://ideas.powerbi.com/) +- Questions? [Try asking the Fabric Community](https://community.fabric.microsoft.com/) +- Suggestions? [Contribute ideas to improve Fabric](https://ideas.fabric.microsoft.com/) diff --git a/powerbi-docs/guidance/relationships-bidirectional-filtering.md b/powerbi-docs/guidance/relationships-bidirectional-filtering.md index 79cdc700cc..7313a5e693 100644 --- a/powerbi-docs/guidance/relationships-bidirectional-filtering.md +++ b/powerbi-docs/guidance/relationships-bidirectional-filtering.md @@ -1,6 +1,6 @@ --- title: "Bi-directional relationship guidance" -description: Guidance for developing bi-directional filtering model relationships. +description: "Guidance for developing bi-directional filtering model relationships." author: denglishbi ms.author: daengli ms.reviewer: maroche @@ -8,105 +8,102 @@ ms.service: powerbi ms.subservice: powerbi-resource ms.topic: conceptual ms.custom: fabric-cat -ms.date: 11/10/2023 +ms.date: 12/27/2024 --- # Bi-directional relationship guidance -This article targets you as a data modeler working with Power BI Desktop. It provides you with guidance on when to create bi-directional model relationships. A bi-directional relationship is one that filters in _both directions_. +This article targets you as a data modeler who works with Power BI Desktop. It provides you with guidance on when to create bi-directional model relationships. A bi-directional relationship is one that filters in _both directions_. [!INCLUDE [relationships-prerequisite-reading](includes/relationships-prerequisite-reading.md)] -Generally, we recommend minimizing the use of bi-directional relationships. They can negatively impact on model query performance, and possibly deliver confusing experiences for your report users. +Generally, we recommend that you minimize the use of bi-directional relationships. That's because they can negatively impact on model query performance, and possibly deliver confusing experiences for your report users. -There are three scenarios when bi-directional filtering can solve specific requirements: +However, there are three scenarios when bi-directional filtering can solve specific requirements: - [Special model relationships](#special-model-relationships) -- [Slicer items "with data"](#slicer-items-with-data) +- [Slicer options "with data"](#slicer-options-with-data) - [Dimension-to-dimension analysis](#dimension-to-dimension-analysis) ## Special model relationships Bi-directional relationships play an important role when creating the following two special model relationship types: -- **One-to-one**: All one-to-one relationships must be bi-directional—it isn't possible to configure otherwise. Generally, we don't recommend creating these types of relationships. For a complete discussion and alternative designs, see [One-to-one relationship guidance](relationships-one-to-one.md). -- **Many-to-many**: When relating two dimension-type tables, a bridging table is required. A bi-directional filter is required to ensure filters propagate across the bridging table. For more information, see [Many-to-many relationship guidance (Relate many-to-many dimensions)](relationships-many-to-many.md#relate-many-to-many-dimensions). +- **One-to-one**: All one-to-one relationships must be bi-directional—it isn't possible to configure otherwise. Generally, we don't recommend creating these types of relationships. For a complete discussion and alternative design patterns, see [One-to-one relationship guidance](relationships-one-to-one.md). +- **Many-to-many**: When relating two [dimension tables](star-schema.md#dimension-tables), a [bridging table](star-schema.md#factless-fact-tables) is required. A bi-directional filter is required to ensure filters propagate across the bridging table. For more information, see [Many-to-many relationship guidance](relationships-many-to-many.md#relate-many-to-many-dimensions). -## Slicer items "with data" +## Slicer options "with data" -Bi-directional relationships can deliver slicers that limit items to where data exists. (If you're familiar with Excel PivotTables and slicers, it's the default behavior when sourcing data from a Power BI semantic model, or an Analysis Services model.) To help explain what it means, first consider the following model diagram. +Bi-directional relationships can deliver slicers that limit options to where data exists. (If you're familiar with Excel PivotTables and slicers, it's the default behavior when sourcing data from a Power BI semantic model or an Analysis Services model.) To help explain what it means, first consider the following model diagram. -![Diagram showing a model containing three tables. The design is described in the following paragraph.](media/relationships-bidirectional-filtering/sales-model-diagram.png) +:::image type="content" source="media/relationships-bidirectional-filtering/sales-model-diagram.svg" alt-text="Diagram showing a model containing three tables. The design is described in the following paragraph." border="false"::: -The first table is named **Customer**, and it contains three columns: **Country-Region**, **Customer**, and **CustomerCode**. The second table is named **Product**, and it contains three columns: **Color**, **Product**, and **SKU**. The third table is named **Sales**, and it contains four columns: **CustomerCode**, **OrderDate**, **Quantity**, and **SKU**. The **Customer** and **Product** tables are dimension-type tables, and each has a one-to-many relationship to the **Sales** table. Each relationship filters in a single direction. +The first table is named `Customer`., and it contains three columns: `Country-Region`, `Customer`, and `CustomerCode`. The second table is named `Product`, and it contains three columns: `Color`, `Product`, and `SKU`. The third table is named `Sales`, and it contains four columns: `CustomerCode`, `OrderDate`, `Quantity`, and `SKU`. The `Customer` and `Product` tables are dimension tables, and each has a one-to-many relationship to the `Sales` table. Each relationship filters in a single direction. To help describe how bi-directional filtering works, the model diagram has been modified to reveal the table rows. All examples in this article are based on this data. -> [!NOTE] -> It's not possible to display table rows in the Power BI Desktop model diagram. It's done in this article to support the discussion with clear examples. - -![Diagram showing that the model now reveals the table rows. The row details are described in the following paragraph.](media/relationships-bidirectional-filtering/sales-model-diagram-rows.png) +:::image type="content" source="media/relationships-bidirectional-filtering/sales-model-diagram-rows.svg" alt-text="Diagram showing that the model now reveals the table rows. The row details are described in the following paragraph." border="false"::: The row details for the three tables are described in the following bulleted list: -- The **Customer** table has two rows: - - **CustomerCode** CUST-01, **Customer** Customer-1, **Country-Region** United States - - **CustomerCode** CUST-02, **Customer** Customer-2, **Country-Region** Australia -- The **Product** table has three rows: - - **SKU** CL-01, **Product** T-shirt, **Color** Green - - **SKU** CL-02, **Product** Jeans, **Color** Blue - - **SKU** AC-01, **Product** Hat, **Color** Blue -- The **Sales** table has three rows: - - **OrderDate** January 1 2019, **CustomerCode** CUST-01, **SKU** CL-01, **Quantity** 10 - - **OrderDate** February 2 2019, **CustomerCode** CUST-01, **SKU** CL-02, **Quantity** 20 - - **OrderDate** March 3 2019, **CustomerCode** CUST-02, **SKU** CL-01, **Quantity** 30 +- The `Customer` table has two rows: + - `CustomerCode` **CUST-01**, `Customer` **Customer-1**, `Country-Region` **United States** + - `CustomerCode` **CUST-02**, `Customer` **Customer-2**, `Country-Region` **Australia** +- The `Product` table has three rows: + - `SKU` **CL-01**, `Product` **T-shirt**, `Color` **Green** + - `SKU` **CL-02**, `Product` **Jeans**, `Color` **Blue** + - `SKU` **AC-01**, `Product` **Hat**, `Color` **Blue** +- The `Sales` table has three rows: + - `OrderDate` **January 1 2019**, `CustomerCode` **CUST-01**, `SKU` **CL-01**, `Quantity` **10** + - `OrderDate` **February 2 2019**, `CustomerCode` **CUST-01**, `SKU` **CL-02**, `Quantity` **20** + - `OrderDate` **March 3 2019**, `CustomerCode` **CUST-02**, `SKU` **CL-01**, `Quantity` **30** Now consider the following report page. -![Diagram showing the report page containing three visuals. The details are described in the following paragraph.](media/relationships-bidirectional-filtering/sales-report-no-bi-directional-filter.png) +:::image type="content" source="media/relationships-bidirectional-filtering/sales-report-no-bi-directional-filter.svg" alt-text="Diagram showing the report page containing three visuals. The details are described in the following paragraph." border="false"::: -The page consists of two slicers and a card visual. The first slicer is for **Country-Region** and it has two items: Australia and United States. It currently slices by Australia. The second slicer is for **Product**, and it has three items: Hat, Jeans, and T-shirt. No items are selected (meaning _no products_ are filtered). The card visual displays a quantity of 30. +The page consists of two slicers and a card visual. The first slicer is based on the `Country-Region` field, and it has two options: Australia and United States. It currently slices by Australia. The second slicer is based on the `Product` field, and it has three options: Hat, Jeans, and T-shirt. No items are selected (meaning _no products_ are filtered). The card visual displays a quantity of 30. -When report users slice by Australia, you might want to limit the **Product** slicer to display items where data _relates_ to Australian sales. It's what's meant by showing slicer items "with data". You can achieve this behavior by configuring the relationship between the **Product** and **Sales** table to filter in both directions. +When report users slice by Australia, you might want to limit the product slicer to display options where data _relates_ to Australian sales. That's what's meant by showing slicer options "with data". You can achieve this behavior by setting the relationship between the `Product` and `Sales` tables to filter _in both directions_. -![Diagram showing a model that the relationship between the Product and Sales table is now bi-directional.](media/relationships-bidirectional-filtering/sales-model-diagram-rows-bi-directional-filter.png) +:::image type="content" source="media/relationships-bidirectional-filtering/sales-model-diagram-rows-bi-directional-filter.svg" alt-text="Diagram showing a model that the relationship between the Product and Sales tables is now bi-directional." border="false"::: -The **Product** slicer now lists a single item: T-shirt. This item represents the only product sold to Australian customers. +The product slicer now lists a single option: T-shirt. This option represents the only product sold to Australian customers. -![Diagram showing the report page containing three visuals with Product called out. The details are described in the following paragraph.](media/relationships-bidirectional-filtering/sales-report-bi-directional-filter.png) +:::image type="content" source="media/relationships-bidirectional-filtering/sales-report-bi-directional-filter.svg" alt-text="Diagram showing the report page containing three visuals with Product called out. The details are described in the following paragraph." border="false"::: -We first suggest you consider carefully whether this design works for your report users. Some report users find the experience confusing. They don't understand why slicer items dynamically appear or disappear when they interact with other slicers. +First, we recommend that you consider carefully whether this design works for your report users. Some report users find the experience confusing because they don't understand why slicer options dynamically appear or disappear when they interact with other slicers. -If you do decide to show slicer items "with data", we don't recommend you configure bi-directional relationships. Bi-directional relationships require more processing and so they can negatively impact on query performance—especially as the number of bi-directional relationships in your model increases. +If you do decide to show slicer options "with data", we don't recommend you set up a bi-directional relationships. Bi-directional relationships require more processing and so they can negatively impact on query performance—especially as the number of bi-directional relationships in the model increases. -There's a better way to achieve the same result: Instead of using bi-directional filters, you can apply a visual-level filter to the **Product** slicer itself. +There's a better way to achieve the same result: Instead of using bi-directional filters, you can apply a visual-level filter to the product slicer itself. -Let's now consider that the relationship between the **Product** and **Sales** table no longer filters in both directions. And, the following measure definition has been added to the **Sales** table. +Let's now consider that the relationship between the `Product` and `Sales` tables no longer filters in both directions. And, the following measure definition has been added to the `Sales` table. ```dax Total Quantity = SUM(Sales[Quantity]) ``` -To show the **Product** slicer items "with data", it simply needs to be filtered by the **Total Quantity** measure using the "is not blank" condition. +To show the product slicer options "with data", it simply needs to be filtered by the `Total Quantity` measure by using the "is not blank" condition. -![Diagram showing that the Filters pane for the Product slicer now filters by "Total Quantity is not blank".](media/relationships-bidirectional-filtering/filter-product-slicer-measure-is-not-blank.png) +:::image type="content" source="media/relationships-bidirectional-filtering/filter-product-slicer-measure-is-not-blank.svg" alt-text="Diagram showing that the Filters pane for the Product slicer now filters by Total Quantity is not blank." border="false"::: ## Dimension-to-dimension analysis -A different scenario involving bi-directional relationships treats a fact-type table like a bridging table. This way, it supports analyzing dimension-type table data within the filter context of a different dimension-type table. +A different scenario involving bi-directional relationships treats a [fact table](star-schema.md#fact-tables) like a [bridging table](star-schema.md#factless-fact-tables). This way, it supports analyzing dimension table data within the filter context of a different dimension table. Using the example model in this article, consider how the following questions can be answered: - How many colors were sold to Australian customers? - How many countries/regions purchased jeans? -Both questions can be answered _without_ summarizing data in the bridging fact-type table. They do, however, require that filters propagate from one dimension-type table to the other. Once filters propagate via the fact-type table, summarization of dimension-type table columns can be achieved using the [DISTINCTCOUNT](/dax/distinctcount-function-dax) DAX function—and possibly the [MIN](/dax/min-function-dax) and [MAX](/dax/max-function-dax) DAX functions. +Both questions can be answered _without_ summarizing data in the bridging fact table. They do, however, require that filters propagate from one dimension table to the other. When filters propagate via the fact table, summarization of dimension table columns can be achieved using the [DISTINCTCOUNT](/dax/distinctcount-function-dax) DAX function—and possibly the [MIN](/dax/min-function-dax) and [MAX](/dax/max-function-dax) DAX functions. -As the fact-type table behaves like a bridging table, you can follow the many-to-many relationship guidance to relate two dimension-type tables. It will require configuring at least one relationship to filter in both directions. For more information, see [Many-to-many relationship guidance (Relate many-to-many dimensions)](relationships-many-to-many.md#relate-many-to-many-dimensions). +As the fact table behaves like a bridging table, you can apply the many-to-many relationship guidance to relate two dimension tables. It will require setting up at least one relationship to filter in both directions. For more information, see [Many-to-many relationship guidance](relationships-many-to-many.md#relate-many-to-many-dimensions). -However, as already described in this article, this design will likely result in a negative impact on performance, and the user experience consequences related to [slicer items "with data"](#slicer-items-with-data). So, we recommend that you activate bi-directional filtering _in a measure definition_ by using the [CROSSFILTER](/dax/crossfilter-function) DAX function instead. The CROSSFILTER function can be used to modify filter directions—or even disable the relationship—during the evaluation of an expression. +However, as already described in this article, this design will likely result in a negative impact on performance, and the user experience consequences related to [slicer options "with data"](#slicer-options-with-data). So, we recommend that you activate bi-directional filtering _in a measure definition_ by using the [CROSSFILTER](/dax/crossfilter-function) DAX function instead. You can use the CROSSFILTER function to modify filter directions—or even disable the relationship—during the evaluation of an expression. -Consider the following measure definition added to the **Sales** table. In this example, the model relationship between the **Customer** and **Sales** tables has been configured to filter in a _single direction_. +Consider the following measure definition added to the `Sales` table. In this example, the model relationship between the `Customer` and `Sales` tables has been set up to filter in a _single direction_. ```dax Different Countries Sold = @@ -120,11 +117,11 @@ CALCULATE( ) ``` -During the evaluation of the **Different Countries Sold** measure expression, the relationship between the **Customer** and **Sales** tables filters in both directions. +During the evaluation of the `Different Countries Sold` measure, the relationship between the `Customer` and `Sales` tables filters in both directions. -The following table visual present statistics for each product sold. The **Quantity** column is simply the sum of quantity values. The **Different Countries Sold** column represents the distinct count of country-region values of all customers who have purchased the product. +The following table visual present statistics for each product sold. The `Quantity` column is simply the sum of quantity values. The `Different Countries Sold` column represents the distinct count of country-region values of all customers who have purchased the product. -![Diagram showing that two products are listed in a table visual. In the "Different Countries Sold" column, Jeans is 1, and T-shirt is 2.](media/relationships-bidirectional-filtering/country-sales-crossfilter-function.png) +:::image type="content" source="media/relationships-bidirectional-filtering/country-sales-crossfilter-function.svg" alt-text="Diagram showing that two products are listed in a table visual. In the Different Countries Sold column, Jeans is 1, and T-shirt is 2." border="false"::: ## Related content @@ -135,5 +132,5 @@ For more information related to this article, check out the following resources: - [One-to-one relationship guidance](relationships-one-to-one.md) - [Many-to-many relationship guidance](relationships-many-to-many.md) - [Relationship troubleshooting guidance](relationships-troubleshoot.md) -- Questions? [Try asking the Power BI Community](https://community.powerbi.com/) -- Suggestions? [Contribute ideas to improve Power BI](https://ideas.powerbi.com/) \ No newline at end of file +- Questions? [Try asking the Fabric Community](https://community.fabric.microsoft.com/) +- Suggestions? [Contribute ideas to improve Fabric](https://ideas.fabric.microsoft.com/) diff --git a/powerbi-docs/guidance/relationships-many-to-many.md b/powerbi-docs/guidance/relationships-many-to-many.md index 2240acc4db..2e6eb3b269 100644 --- a/powerbi-docs/guidance/relationships-many-to-many.md +++ b/powerbi-docs/guidance/relationships-many-to-many.md @@ -1,6 +1,6 @@ --- -title: Many-to-many relationship guidance -description: Guidance for developing many-to-many model relationships. +title: "Many-to-many relationship guidance" +description: "Guidance for developing many-to-many model relationships." author: denglishbi ms.author: daengli ms.reviewer: maroche @@ -8,213 +8,207 @@ ms.service: powerbi ms.subservice: powerbi-resource ms.topic: conceptual ms.custom: fabric-cat -ms.date: 03/17/2022 +ms.date: 12/27/2024 --- # Many-to-many relationship guidance -This article targets you as a data modeler working with Power BI Desktop. It describes three different many-to-many modeling scenarios. It also provides you with guidance on how to successfully design for them in your models. +This article targets you as a data modeler who works with Power BI Desktop. It describes three different many-to-many modeling scenarios. It also provides you with guidance on how to successfully design for them in your models. [!INCLUDE [relationships-prerequisite-reading](includes/relationships-prerequisite-reading.md)] -There are, in fact, three many-to-many scenarios. They can occur when you're required to: +There are three different many-to-many scenarios. They can occur when you're required to: -- [Relate two dimension-type tables](#relate-many-to-many-dimensions) -- [Relate two fact-type tables](#relate-many-to-many-facts) -- [Relate higher grain fact-type tables](#relate-higher-grain-facts), when the fact-type table stores rows at a higher grain than the dimension-type table rows - -> [!NOTE] -> Power BI now natively supports many-to-many relationships. For more information, see [Apply many-many relationships in Power BI Desktop](../transform-model/desktop-many-to-many-relationships.md). +- [Relate two dimension tables](#relate-many-to-many-dimensions) +- [Relate two fact tables](#relate-many-to-many-facts) +- [Relate higher grain fact tables](#relate-higher-grain-facts), when the [fact table](star-schema.md#fact-tables) stores rows at a higher grain than the dimension table rows ## Relate many-to-many dimensions -Let's consider the first many-to-many scenario type with an example. The classic scenario relates two entities: bank customers and bank accounts. Consider that customers can have multiple accounts, and accounts can have multiple customers. When an account has multiple customers, they're commonly called _joint account holders_. +The classic many-to-many scenario relates two entities, for example bank customers and bank accounts. Consider that customers can have multiple accounts, and accounts can have multiple customers. When an account has multiple customers, they're commonly called _joint account holders_. -Modeling these entities is straight forward. One dimension-type table stores accounts, and another dimension-type table stores customers. As is characteristic of dimension-type tables, there's an ID column in each table. To model the relationship between the two tables, a third table is required. This table is commonly referred to as a _bridging table_. In this example, it's purpose is to store one row for each customer-account association. Interestingly, when this table only contains ID columns, it's called a [_factless fact table_](star-schema.md#factless-fact-tables). +Modeling these entities is straight forward. One [dimension table](star-schema.md#dimension-tables) stores accounts, and another dimension table stores customers. As is characteristic of dimension tables, there's a unique identifier (ID) column in each table. To model the relationship between the two tables, a third table is required. This table is commonly referred to as a _bridging table_. In this example, it's purpose is to store one row for each customer-account association. Interestingly, when this table only contains identifier columns, it's called a [factless fact table](star-schema.md#factless-fact-tables). -Here's a simplistic model diagram of the three tables. +Here's a simplistic diagram of the three model tables. -![Diagram showing a model containing three tables. The design is described in the following paragraph.](media/relationships-many-to-many/bank-account-customer-model-example.png) +:::image type="content" source="media/relationships-many-to-many/bank-account-customer-model-example.svg" alt-text="Diagram showing three model tables. The design is described in the following paragraph." border="false"::: -The first table is named **Account**, and it contains two columns: **AccountID** and **Account**. The second table is named **AccountCustomer**, and it contains two columns: **AccountID** and **CustomerID**. The third table is named **Customer**, and it contains two columns: **CustomerID** and **Customer**. Relationships don't exist between any of the tables. +The first table is named `Account`, and it contains two columns: `AccountID` and `Account`. The second table is named `AccountCustomer`, and it contains two columns: `AccountID` and `CustomerID`. The third table is named `Customer`, and it contains two columns: `CustomerID` and `Customer`. Relationships don't exist between any of the tables. -Two one-to-many relationships are added to relate the tables. Here's an updated model diagram of the related tables. A fact-type table named **Transaction** has been added. It records account transactions. The bridging table and all ID columns have been hidden. +Two one-to-many relationships are added to relate the tables. Here's an updated model diagram of the related tables. A fact table named `Transaction` has been added. It records account transactions. The bridging table and all identifier columns have been hidden. -![Diagram showing that the model now contains four tables. One-to-many relationships have been added to relate all tables.](media/relationships-many-to-many/bank-account-customer-model-related-tables-1.png) +:::image type="content" source="media/relationships-many-to-many/bank-account-customer-model-related-tables-1.svg" alt-text="Diagram showing that a model diagram comprising four tables. One-to-many relationships have been added to relate all tables." border="false"::: To help describe how the relationship filter propagation works, the model diagram has been modified to reveal the table rows. -> [!NOTE] -> It's not possible to display table rows in the Power BI Desktop model diagram. It's done in this article to support the discussion with clear examples. - -![Diagram showing that the model now reveals the table rows. The row details for the four tables are described in the following paragraph.](media/relationships-many-to-many/bank-account-customer-model-related-tables-2.png) - -The row details for the four tables are described in the following bulleted list: - -- The **Account** table has two rows: - - **AccountID** 1 is for Account-01 - - **AccountID** 2 is for Account-02 -- The **Customer** table has two rows: - - **CustomerID** 91 is for Customer-91 - - **CustomerID** 92 is for Customer-92 -- The **AccountCustomer** table has three rows: - - **AccountID** 1 is associated with **CustomerID** 91 - - **AccountID** 1 is associated with **CustomerID** 92 - - **AccountID** 2 is associated with **CustomerID** 92 -- The **Transaction** table has three rows: - - **Date** January 1 2019, **AccountID** 1, **Amount** 100 - - **Date** February 2 2019, **AccountID** 2, **Amount** 200 - - **Date** March 3 2019, **AccountID** 1, **Amount** -25 +:::image type="content" source="media/relationships-many-to-many/bank-account-customer-model-related-tables-2.svg" alt-text="Diagram showing the model tables and their rows. The row details for the four tables are described in the following paragraph." border="false"::: + +The row details for the four tables are presented in the following bulleted list: + +- The `Account` table has two rows: + - `AccountID` **1** is for **Account-01** + - `AccountID` **2** is for **Account-02** +- The `Customer` table has two rows: + - `CustomerID` **91** is for **Customer-91** + - `CustomerID` **92** is for **Customer-92** +- The `AccountCustomer` table has three rows: + - `AccountID` **1** is associated with `CustomerID` **91** + - `AccountID` **1** is associated with `CustomerID` **92** + - `AccountID` **2** is associated with `CustomerID` **92** +- The `Transaction` table has three rows: + - `Date` **January 1 2019**, `AccountID` **1**, `Amount` **100** + - `Date` **February 2 2019**, `AccountID` **2**, `Amount` **200** + - `Date` **March 3 2019**, `AccountID` **1**, `Amount` **-25** Let's see what happens when the model is queried. -Below are two visuals that summarize the **Amount** column from the **Transaction** table. The first visual groups by account, and so the sum of the **Amount** columns represents the _account balance_. The second visual groups by customer, and so the sum of the **Amount** columns represents the _customer balance_. +In the following image, there are two table visuals that summarize the `Amount` column of the `Transaction` table. The first visual groups by account, and so the sum of the `Amount` columns represents the _account balance_. The second visual groups by customer, and so the sum of the `Amount` columns represents the _customer balance_. -![Diagram showing two report visuals sitting side by side. The visuals are described in the following paragraph.](media/relationships-many-to-many/bank-account-customer-model-queried-1.png) +:::image type="content" source="media/relationships-many-to-many/bank-account-customer-model-queried-1.svg" alt-text="Diagram showing two table visuals sitting side by side. The visuals are described in the following paragraph." border="false"::: -The first visual is titled **Account Balance**, and it has two columns: **Account** and **Amount**. It displays the following result: +The first table visual (Account Balance) has two columns: `Account` and `Amount`. It displays the following result: -- Account-01 balance amount is 75 -- Account-02 balance amount is 200 -- The total is 275 +- **Account-01** balance amount is **75**. +- **Account-02** balance amount is **200**. +- The total is **275**. -The second visual is titled **Customer Balance**, and it has two columns: **Customer** and **Amount**. It displays the following result: +The second table visual (Customer Balance) has two columns: `Customer` and `Amount`. It displays the following result: -- Customer-91 balance amount is 275 -- Customer-92 balance amount is 275 -- The total is 275 +- **Customer-91** balance amount is **275**. +- **Customer-92** balance amount is **275**. +- The total is **275**. -A quick glance at the table rows and the **Account Balance** visual reveals that the result is correct, for each account and the total amount. It's because each account grouping results in a filter propagation to the **Transaction** table for that account. +A quick glance at the table rows and the Account Balance visual reveals that the result is correct, for each account and the total amount. That's because each account grouping results in a filter propagation to the `Transaction` table for that account. -However, something doesn't appear correct with the **Customer Balance** visual. Each customer in the **Customer Balance** visual has the same balance as the total balance. This result could only be correct if every customer was a joint account holder of every account. That's not the case in this example. The issue is related to filter propagation. It's not flowing all the way to the **Transaction** table. +However, something doesn't appear correct with the Customer Balance visual. Each customer in this visual has the same balance as the total balance. This result could only be correct if every customer was a joint account holder of every account. That's not the case in this example. There's an issue, and it's related to filter propagation. Filters aren't flowing all the way to the `Transaction` table. -Follow the relationship filter directions from the **Customer** table to the **Transaction** table. It should be apparent that the relationship between the **Account** and **AccountCustomer** table is propagating in the wrong direction. The filter direction for this relationship must be set to **Both**. +If you follow the relationship filter directions from the `Customer` table to the `Transaction` table, you can determine that the relationship between the `Account` and `AccountCustomer` tables is propagating in the wrong direction. The filter direction for this relationship must be set to `Both`. -![Diagram showing that the model has been updated. It now filters in both directions.](media/relationships-many-to-many/bank-account-customer-model-related-tables-3.png) +:::image type="content" source="media/relationships-many-to-many/bank-account-customer-model-related-tables-3.svg" alt-text="Diagram showing that the model has been updated. It now filters in both directions." border="false"::: -![Diagram showing the same two report visuals sitting side by side. The first visual has not changed, while the second visual has.](media/relationships-many-to-many/bank-account-customer-model-queried-2.png) +:::image type="content" source="media/relationships-many-to-many/bank-account-customer-model-queried-2.svg" alt-text="Diagram showing the same two report visuals sitting side by side. The first visual hasn't changed, while the second visual has." border="false"::: -As expected, there has been no change to the **Account Balance** visual. +As expected, there has been no change to the Account Balance visual. -The **Customer Balance** visuals, however, now displays the following result: +The Customer Balance visual, however, now displays the following result: -- Customer-91 balance amount is 75 -- Customer-92 balance amount is 275 -- The total is 275 +- **Customer-91** balance amount is **75**. +- **Customer-92** balance amount is **275**. +- The total is **275**. -The **Customer Balance** visual now displays a correct result. Follow the filter directions for yourself, and see how the customer balances were calculated. Also, understand that the visual total means _all customers_. +The Customer Balance visual now displays a correct result. Follow the filter directions for yourself, and see how the customer balances were calculated. Also, understand that the visual total means _all customers_. -Someone unfamiliar with the model relationships could conclude that the result is incorrect. They might ask: _Why isn't the total balance for **Customer-91** and **Customer-92** equal to 350 (75 + 275)?_ +Someone unfamiliar with the model relationships could conclude that the result is incorrect. They might ask: _Why isn't the total balance for `Customer-91` and `Customer-92` equal to 350 (75 + 275)?_ The answer to their question lies in understanding the many-to-many relationship. Each customer balance can represent the addition of multiple account balances, and so the customer balances are _non-additive_. ### Relate many-to-many dimensions guidance -When you have a many-to-many relationship between dimension-type tables, we provide the following guidance: +When you have a many-to-many relationship between dimension tables, follow this guidance: -- Add each many-to-many related entity as a model table, ensuring it has a unique identifier (ID) column -- Add a bridging table to store associated entities -- Create one-to-many relationships between the three tables -- Configure **one** bi-directional relationship to allow filter propagation to continue to the fact-type tables -- When it isn't appropriate to have missing ID values, set the **Is Nullable** property of ID columns to FALSE—data refresh will then fail if missing values are sourced -- Hide the bridging table (unless it contains additional columns or measures required for reporting) -- Hide any ID columns that aren't suitable for reporting (for example, when IDs are surrogate keys) -- If it makes sense to leave an ID column visible, ensure that it's on the "one" slide of the relationship—always hide the "many" side column. It results in the best filter performance. -- To avoid confusion or misinterpretation, communicate explanations to your report users—you can add descriptions with text boxes or [visual header tooltips](report-page-tooltips.md) +- Add each many-to-many related entity as a model table, ensuring it has an ID column. +- Add a bridging table to store associated entities. +- Create one-to-many relationships between the three tables. +- Set _one_ bi-directional relationship to allow filter propagation to continue to the fact table. +- When it isn't appropriate to have missing ID values, disable the `Is Nullable` property—data refresh will fail when missing values are sourced. +- Hide the bridging table (unless it contains other columns or measures required for reporting). +- Hide any ID columns that aren't suitable for reporting (for example, when the columns store surrogate key values). +- If it makes sense to leave an ID column visible, ensure that it's on the "one" side of the relationship—always hide the "many" side column. That's because filters applied to the "one" slide result in better filter performance. +- To avoid confusion or misinterpretation, communicate explanations to your report users—you can add descriptions with text boxes or [visual header tooltips](report-page-tooltips.md). -We don't recommend you relate many-to-many dimension-type tables directly. This design approach requires configuring a relationship with a many-to-many cardinality. Conceptually it can be achieved, yet it implies that the related columns will contain duplicate values. It's a well-accepted design practice, however, that dimension-type tables have an ID column. Dimension-type tables should always use the ID column as the "one" side of a relationship. +We don't recommend that you relate many-to-many dimension tables directly. This design approach requires setting up a relationship with a many-to-many cardinality. Conceptually it can be achieved, yet it implies that the related columns might contain duplicate values. It's a well-accepted design practice, however, that dimension tables have an ID column. Dimension tables should always use the ID column as the "one" side of a relationship. ## Relate many-to-many facts -The second many-to-many scenario type involves relating two fact-type tables. Two fact-type tables can be related directly. This design technique can be useful for quick and simple data exploration. However, and to be clear, we generally don't recommend this design approach. We'll explain why later in this section. +A different many-to-many scenario type involves relating two fact tables. Two fact tables can be related directly. This design technique can be useful for quick and simple data exploration. However, and to be clear, we generally don't recommend this design approach. We'll explain why later in this section. -Let's consider an example that involves two fact-type tables: **Order** and **Fulfillment**. The **Order** table contains one row per order line, and the **Fulfillment** table can contains zero or more rows per order line. Rows in the **Order** table represent sales orders. Rows in the **Fulfillment** table represent order items that have been shipped. A many-to-many relationship relates the two **OrderID** columns, with filter propagation only from the **Order** table (**Order** filters **Fulfillment**). +Let's consider an example that involves two fact tables: `Order` and `Fulfillment`. The `Order` table contains one row per order line, and the `Fulfillment` table can contains zero or more rows per order line. Rows in the `Order` table represent sales orders. Rows in the `Fulfillment` table represent order items that have been shipped. A many-to-many relationship relates the `OrderID` columns in each table, with filter propagation only from the `Order` table (meaning the `Order` table filters the `Fulfillment` table). -![Diagram showing a model containing two tables: Order and Fulfillment.](media/relationships-many-to-many/order-fulfillment-model-example.png) +:::image type="content" source="media/relationships-many-to-many/order-fulfillment-model-example.svg" alt-text="Diagram showing a model containing two tables: Order and Fulfillment." border="false"::: -The relationship cardinality is set to many-to-many to support storing duplicate **OrderID** values in both tables. In the **Order** table, duplicate **OrderID** values can exist because an order can have multiple lines. In the **Fulfillment** table, duplicate **OrderID** values can exist because orders may have multiple lines, and order lines can be fulfilled by many shipments. +The relationship cardinality is set to `Many-to-many` to support storing duplicate `OrderID` column values in both tables. In the `Order` table, duplicate ID values can exist because an order can have multiple lines. In the `Fulfillment` table, duplicate ID values can exist because orders can have multiple lines, and order lines can be fulfilled by many shipments. -Let's now take a look at the table rows. In the **Fulfillment** table, notice that order lines can be fulfilled by multiple shipments. (The absence of an order line means the order is yet to be fulfilled.) +Let's now take a look at the table rows. In the `Fulfillment` table, notice that order lines can be fulfilled by multiple shipments. (The absence of an order line means the order is yet to be fulfilled.) -![Diagram showing that the model now reveals the table rows. The row details for the two tables are described in the following paragraph.](media/relationships-many-to-many/order-fulfillment-model-related-tables.png) +:::image type="content" source="media/relationships-many-to-many/order-fulfillment-model-related-tables.svg" alt-text="Diagram showing the model table rows. The row details for the two tables are described in the following paragraph." border="false"::: The row details for the two tables are described in the following bulleted list: -- The **Order** table has five rows: - - **OrderDate** January 1 2019, **OrderID** 1, **OrderLine** 1, **ProductID** Prod-A, **OrderQuantity** 5, **Sales** 50 - - **OrderDate** January 1 2019, **OrderID** 1, **OrderLine** 2, **ProductID** Prod-B, **OrderQuantity** 10, **Sales** 80 - - **OrderDate** February 2 2019, **OrderID** 2, **OrderLine** 1, **ProductID** Prod-B, **OrderQuantity** 5, **Sales** 40 - - **OrderDate** February 2 2019, **OrderID** 2, **OrderLine** 2, **ProductID** Prod-C, **OrderQuantity** 1, **Sales** 20 - - **OrderDate** March 3 2019, **OrderID** 3, **OrderLine** 1, **ProductID** Prod-C, **OrderQuantity** 5, **Sales** 100 -- The **Fulfillment** table has four rows: - - **FulfillmentDate** January 1 2019, **FulfillmentID** 50, **OrderID** 1, **OrderLine** 1, **FulfillmentQuantity** 2 - - **FulfillmentDate** February 2 2019, **FulfillmentID** 51, **OrderID** 2, **OrderLine** 1, **FulfillmentQuantity** 5 - - **FulfillmentDate** February 2 2019, **FulfillmentID** 52, **OrderID** 1, **OrderLine** 1, **FulfillmentQuantity** 3 - - **FulfillmentDate** January 1 2019, **FulfillmentID** 53, **OrderID** 1, **OrderLine** 2, **FulfillmentQuantity** 10 +- The `Order` table has five rows: + - `OrderDate` **January 1 2019**, `OrderID` **1**, `OrderLine` **1**, `ProductID` **Prod-A**, `OrderQuantity` **5**, `Sales` **50** + - `OrderDate` **January 1 2019**, `OrderID` **1**, `OrderLine` **2**, `ProductID` **Prod-B**, `OrderQuantity` **10**, `Sales` **80** + - `OrderDate` **February 2 2019**, `OrderID` **2**, `OrderLine` **1**, `ProductID` **Prod-B**, `OrderQuantity` **5**, `Sales` **40** + - `OrderDate` **February 2 2019**, `OrderID` **2**, `OrderLine` **2**, `ProductID` **Prod-C**, `OrderQuantity` **1**, `Sales` **20** + - `OrderDate` **March 3 2019**, `OrderID` **3**, `OrderLine` **1**, `ProductID` **Prod-C**, `OrderQuantity` **5**, `Sales` **100** +- The `Fulfillment` table has four rows: + - `FulfillmentDate` **January 1 2019**, `FulfillmentID` **50**, `OrderID` **1**, `OrderLine` **1**, `FulfillmentQuantity` **2** + - `FulfillmentDate` **February 2 2019**, `FulfillmentID` **51**, `OrderID` **2**, `OrderLine` **1**, `FulfillmentQuantity` **5** + - `FulfillmentDate` **February 2 2019**, `FulfillmentID` **52**, `OrderID` **1**, `OrderLine` **1**, `FulfillmentQuantity` **3** + - `FulfillmentDate` **January 1 2019**, `FulfillmentID` **53**, `OrderID` **1**, `OrderLine` **2**, `FulfillmentQuantity` **10** -Let's see what happens when the model is queried. Here's a table visual comparing order and fulfillment quantities by the **Order** table **OrderID** column. +Let's see what happens when the model is queried. Here's a table visual comparing order and fulfillment quantities by the `Order` table `OrderID` column. -![Diagram showing a table visual with three columns: OrderID, OrderQuantity, and FulfillmentQuantity.](media/relationships-many-to-many/order-fulfillment-model-queried.png) +:::image type="content" source="media/relationships-many-to-many/order-fulfillment-model-queried.svg" alt-text="Diagram showing a table visual with three columns: OrderID, OrderQuantity, and FulfillmentQuantity." border="false"::: -The visual presents an accurate result. However, the usefulness of the model is limited—you can only filter or group by the **Order** table **OrderID** column. +The visual presents an accurate result. However, the usefulness of the model is limited because you can only filter or group by the `Order` table `OrderID` column. ### Relate many-to-many facts guidance -Generally, we don't recommend relating two fact-type tables directly using many-to-many cardinality. The main reason is because the model won't provide flexibility in the ways you report visuals filter or group. In the example, it's only possible for visuals to filter or group by the **Order** table **OrderID** column. An additional reason relates to the quality of your data. If your data has integrity issues, it's possible some rows may be omitted during querying due to the nature of the _limited relationship_. For more information, see [Model relationships in Power BI Desktop (Relationship evaluation)](../transform-model/desktop-relationships-understand.md#relationship-evaluation). +Generally, we don't recommend that you relate two fact tables directly by using many-to-many cardinality. The main reason is because the model won't provide flexibility in the ways your report visuals filter or group. In the example, it's only possible for visuals to filter or group by the `Order` table `OrderID` column. Another reason relates to the quality of your data. If your data has integrity issues, it's possible some rows might be omitted during querying due to the nature many-to-man cardinality and [limited relationships](../transform-model/desktop-relationships-understand.md#relationship-evaluation). -Instead of relating fact-type tables directly, we recommend you adopt [Star Schema](star-schema.md) design principles. You do it by adding dimension-type tables. The dimension-type tables then relate to the fact-type tables by using one-to-many relationships. This design approach is robust as it delivers flexible reporting options. It lets you filter or group using any of the dimension-type columns, and summarize any related fact-type table. +Instead of relating fact tables directly, we recommend that you implement a [star schema](star-schema.md) design. That means you add dimension tables. These dimension tables then relate to the fact tables by using one-to-many relationships. This design approach is robust as it efficiently delivers flexible reporting options. It lets you filter or group by using any of the dimension table columns, and summarize columns of any related fact table. Let's consider a better solution. -![Diagram showing a model includes six tables: OrderLine, OrderDate, Order, Fulfillment, Product, and FulfillmentDate.](media/relationships-many-to-many/order-fulfillment-model-improved.png) +:::image type="content" source="media/relationships-many-to-many/order-fulfillment-model-improved.svg" alt-text="Diagram showing a model comprising six tables: OrderLine, OrderDate, Order, Fulfillment, Product, and FulfillmentDate." border="false"::: Notice the following design changes: -- The model now has four additional tables: **OrderLine**, **OrderDate**, **Product**, and **FulfillmentDate** -- The four additional tables are all dimension-type tables, and one-to-many relationships relate these tables to the fact-type tables -- The **OrderLine** table contains an **OrderLineID** column, which represents the **OrderID** value multiplied by 100, plus the **OrderLine** value—a unique identifier for each order line -- The **Order** and **Fulfillment** tables now contain an **OrderLineID** column, and they no longer contain the **OrderID** and **OrderLine** columns -- The **Fulfillment** table now contains **OrderDate** and **ProductID** columns -- The **FulfillmentDate** table relates only to the **Fulfillment** table -- All unique identifier columns are hidden +- The model now has four extra tables: `OrderLine`, `OrderDate`, `Product`, and `FulfillmentDate`. +- The four extra tables are all dimension tables where one-to-many relationships relate them to the fact tables. +- The `OrderLine` table contains the `OrderLineID` column, which stores the `OrderID` value multiplied by 100, plus the `OrderLine` column value—an ID for each order line. +- The `Order` and `Fulfillment` tables now each contain an `OrderLineID` column, and they no longer contain the `OrderID` and `OrderLine` columns. +- The `Fulfillment` table now contains `OrderDate` and `ProductID` columns. +- The `FulfillmentDate` table has a relationship only to the `Fulfillment` table. +- All ID columns are hidden. -Taking the time to apply star schema design principles delivers the following benefits: +Taking the time to adopt a star schema design delivers the following benefits: -- Your report visuals can _filter or group_ by any visible column from the dimension-type tables -- Your report visuals can _summarize_ any visible column from the fact-type tables -- Filters applied to the **OrderLine**, **OrderDate**, or **Product** tables will propagate to both fact-type tables -- All relationships are one-to-many, and each relationship is a _regular relationship_. Data integrity issues won't be masked. For more information, see [Model relationships in Power BI Desktop (Relationship evaluation)](../transform-model/desktop-relationships-understand.md#relationship-evaluation). +- Your report visuals can _filter or group_ by any visible column from the dimension tables. +- Your report visuals can _summarize_ any visible column from the fact tables. +- Filters applied to the `OrderLine`, `OrderDate`, or `Product` tables propagate to both fact tables. +- All relationships are one-to-many, and each relationship is a _regular relationship_. Data integrity issues won't be masked. For more information about relationship evaluation, see [Model relationships in Power BI Desktop](../transform-model/desktop-relationships-understand.md#relationship-evaluation). ## Relate higher grain facts This many-to-many scenario is very different from the other two already described in this article. -Let's consider an example involving four tables: **Date**, **Sales**, **Product**, and **Target**. The **Date** and **Product** are dimension-type tables, and one-to-many relationships relate each to the **Sales** fact-type table. So far, it represents a good star schema design. The **Target** table, however, is yet to be related to the other tables. +Let's consider an example involving four tables: `Date`, `Sales`, `Product`, and `Target`. The `Date` and `Product` tables are dimension tables, and one-to-many relationships relate each to the `Sales` fact table. So far, it represents a good star schema design. The `Target` table, however, is yet to be related to the other tables. -![Diagram showing a model including four tables: Date, Sales, Product, and Target.](media/relationships-many-to-many/sales-targets-model-example.png) +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-example.svg" alt-text="Diagram showing a model comprising four tables: Date, Sales, Product, and Target." border="false"::: -The **Target** table contains three columns: **Category**, **TargetQuantity**, and **TargetYear**. The table rows reveal a granularity of year and product category. In other words, targets—used to measure sales performance—are set each year for each product category. +The `Target` table contains three columns: `Category`, `TargetQuantity`, and `TargetYear`. The table rows reveal a granularity of year and product category. In other words, targets—used to measure sales performance—are set each year for each product category. -![Diagram showing the Target table has three columns: TargetYear, Category, and TargetQuantity.](media/relationships-many-to-many/sales-targets-model-target-rows.png) +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-target-rows.svg" alt-text="Diagram showing the Sales and Target fact tables. The Target fact table has three columns: TargetYear, Category, and TargetQuantity." border="false"::: -Because the **Target** table stores data at a higher level than the dimension-type tables, a one-to-many relationship cannot be created. Well, it's true for just one of the relationships. Let's explore how the **Target** table can be related to the dimension-type tables. +Because the `Target` table stores data at a higher level than the dimension tables, a one-to-many relationship can't be created. Well, it's true for just one of the relationships. Let's explore how the `Target` table can be related to the dimension tables. ### Relate higher grain time periods -A relationship between the **Date** and **Target** tables should be a one-to-many relationship. It's because the **TargetYear** column values are dates. In this example, each **TargetYear** column value is the first date of the target year. +A relationship between the `Date` and `Target` tables should be a one-to-many relationship. That's because the `TargetYear` column values are dates. In this example, each `TargetYear` column stores the first date of the target year. > [!TIP] > When storing facts at a higher time granularity than day, set the column data type to **Date** (or **Whole number** if you're using date keys). In the column, store a value representing the first day of the time period. For example, a year period is recorded as January 1 of the year, and a month period is recorded as the first day of that month. -Care must be taken, however, to ensure that month or date level filters produce a meaningful result. Without any special calculation logic, report visuals may report that target dates are literally the first day of each year. All other days—and all months except January—will summarize the target quantity as BLANK. +Care must be taken, however, to ensure that month or date level filters produce a meaningful result. Without any special calculation logic, report visuals might report that target dates are literally the first day of each year. All other days—and all months except January—will summarize the target quantity as BLANK. -The following matrix visual shows what happens when the report user drills from a year into its months. The visual is summarizing the **TargetQuantity** column. (The [Show items with no data](../create-reports/desktop-show-items-no-data.md) option has been enabled for the matrix rows.) +The following matrix visual shows what happens when the report user drills down from a year into its months. The visual summarizes the `TargetQuantity` column. (The [Show items with no data](../create-reports/desktop-show-items-no-data.md) option has been enabled for the matrix rows.) -![Diagram showing a matrix visual revealing the year 2020 target quantity as 270.](media/relationships-many-to-many/sales-targets-model-matrix-blank-months-bad.png) +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-matrix-blank-months-bad.svg" alt-text="Diagram showing a matrix visual revealing the year 2020 target quantity as 270. It produces incorrect values by date." border="false"::: -To avoid this behavior, we recommend you control the summarization of your fact data by using measures. One way to control the summarization is to return BLANK when lower-level time periods are queried. Another way—defined with some sophisticated DAX—is to apportion values across lower-level time periods. +To avoid this behavior, we recommend that you control the summarization of your fact data by using measures. One way to control the summarization is to return BLANK when lower-level time periods are queried. Another way—defined with some sophisticated DAX—is to apportion values across lower-level time periods. -Consider the following measure definition that uses the [ISFILTERED](/dax/isfiltered-function-dax) DAX function. It only returns a value when the **Date** or **Month** columns aren't filtered. +Consider the following measure definition that uses the [ISFILTERED](/dax/isfiltered-function-dax) DAX function. It only returns a value when the `Date` and `Month` columns aren't filtered. ```dax Target Quantity = @@ -225,39 +219,35 @@ IF( ) ``` -The following matrix visual now uses the **Target Quantity** measure. It shows that all monthly target quantities are BLANK. +The following matrix visual uses the `Target Quantity` measure. It shows that all monthly target quantities are BLANK. -![Diagram showing a matrix visual revealing the year 2020 target quantity as 270 with blank monthly values.](media/relationships-many-to-many/sales-targets-model-matrix-blank-months-good.png) +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-matrix-blank-months-good.svg" alt-text="Diagram showing two matrix visuals. The first reveals the first month target of 2020 as 270 while the second is blank." border="false"::: ### Relate higher grain (non-date) -A different design approach is required when relating a non-date column from a dimension-type table to a fact-type table (and it's at a higher grain than the dimension-type table). +A different design approach is required when relating a non-date column from a dimension table to a fact table (and it's at a higher grain than the dimension table). -The **Category** columns (from both the **Product** and **Target** tables) contains duplicate values. So, there's no "one" for a one-to-many relationship. In this case, you'll need to create a many-to-many relationship. The relationship should propagate filters in a single direction, from the dimension-type table to the fact-type table. +The `Category` columns (from both the `Product` and `Target` tables) contains duplicate values. So, there's no "one" side for a one-to-many relationship. In this case, you'll need to create a many-to-many relationship. The relationship should propagate filters in a single direction, from the dimension table to the fact table. -![Diagram showing a model of the Target and Product tables. A many-to-many relationship relates the two tables.](media/relationships-many-to-many/sales-targets-model-relate-non-date.png) +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-relate-non-date.svg" alt-text="Diagram showing a model of the Target and Product tables. A many-to-many relationship relates the two tables." border="false"::: Let's now take a look at the table rows. -![Diagram showing a model containing two tables: Target and Product. A many-to-many relationship relates the two Category columns.](media/relationships-many-to-many/sales-targets-model-relate-non-date-tables.png) - -In the **Target** table, there are four rows: two rows for each target year (2019 and 2020), and two categories (Clothing and Accessories). In the **Product** table, there are three products. Two belong to the clothing category, and one belongs to the accessories category. One of the clothing colors is green, and the remaining two are blue. - -A table visual grouping by the **Category** column from the **Product** table produces the following result. +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-relate-non-date-tables.svg" alt-text="Diagram showing a model containing two tables: Target and Product. A many-to-many relationship relates the two Category columns." border="false"::: -![Diagram showing a table visual with two columns: Category and TargetQuantity. Accessories is 60, Clothing is 40, and the total is 100.](media/relationships-many-to-many/sales-targets-model-visual-category-targets.png) +In the `Target` table, there are four rows: two rows for each target year (2019 and 2020), and two categories (Clothing and Accessories). In the `Product` table, there are three products. Two belong to the clothing category, and one belongs to the accessories category. One of the clothing colors is green, and the remaining two are blue. -This visual produces the correct result. Let's now consider what happens when the **Color** column from the **Product** table is used to group target quantity. +A table visual grouping by the `Category` column from the `Product` table produces the following result. However, this visual produces the correct result. Let's now consider what happens when the `Color` column from the `Product` table is used to group target quantity. -![Diagram showing a table visual with two columns: Color and TargetQuantity. Blue is 100, Green is 40, and the total is 100.](media/relationships-many-to-many/sales-targets-model-visual-color-targets-bad.png) +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-visual-color-targets-bad.svg" alt-text="Diagram showing two table visuals. The first groups by Category and the second groups by Color. The second visual produces an incorrect result." border="false"::: The visual produces a misrepresentation of the data. What is happening here? -A filter on the **Color** column from the **Product** table results in two rows. One of the rows is for the Clothing category, and the other is for the Accessories category. These two category values are propagated as filters to the **Target** table. In other words, because the color blue is used by products from two categories, _those categories_ are used to filter the targets. +A filter on the `Color` column from the `Product` table results in two rows. One of the rows is for the Clothing category, and the other is for the Accessories category. These two category values are propagated as filters to the `Target` table. In other words, because the color blue is used by products from two categories, _those categories_ are used to filter the targets. -To avoid this behavior, as described earlier, we recommend you control the summarization of your fact data by using measures. +To avoid this behavior, as described earlier, we recommend that you control the summarization of your fact data by using measures. -Consider the following measure definition. Notice that all **Product** table columns that are beneath the category level are tested for filters. +Consider the following measure definition. Notice that all `Product` table columns that are beneath the category level are tested for filters. ```dax Target Quantity = @@ -269,26 +259,26 @@ IF( ) ``` -The following table visual now uses the **Target Quantity** measure. It shows that all color target quantities are BLANK. +The following table visual uses the `Target Quantity` measure. It shows that all color target quantities are BLANK. -![Diagram showing a table visual with two columns: Color and TargetQuantity. Blue is BLANK, Green is BLANK, and the total is 100.](media/relationships-many-to-many/sales-targets-model-visual-color-targets-good.png) +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-visual-color-targets-good.svg" alt-text="Diagram showing two table visuals. The first groups by Category and the second groups by Color. The second visual produces a correct result of blank." border="false"::: The final model design looks like the following. -![Diagram showing a model with Date and Target tables related with a one-to-many relationship.](media/relationships-many-to-many/sales-targets-model-example-final.png) +:::image type="content" source="media/relationships-many-to-many/sales-targets-model-example-final.svg" alt-text="Diagram showing a model with Date and Target tables related with a one-to-many relationship." border="false"::: ### Relate higher grain facts guidance -When you need to relate a dimension-type table to a fact-type table, and the fact-type table stores rows at a higher grain than the dimension-type table rows, we provide the following guidance: +When you need to relate a dimension table to a fact table, and the fact table stores rows at a higher grain than the dimension table rows, follow this guidance: -- For higher grain fact dates: - - In the fact-type table, store the first date of the time period - - Create a one-to-many relationship between the date table and the fact-type table -- For other higher grain facts: - - Create a many-to-many relationship between the dimension-type table and the fact-type table -- For both types: - - Control summarization with measure logic—return BLANK when lower-level dimension-type columns are used to filter or group - - Hide summarizable fact-type table columns—this way, only measures can be used to summarize the fact-type table +- **For higher grain fact dates** + - In the fact table, store the first date of the time period. + - Create a one-to-many relationship between the date table and the fact table. +- **For other higher grain facts** + - Create a many-to-many relationship between the dimension table and the fact table. +- **For both types** + - Control summarization with measure logic—return BLANK when lower-level dimension columns are used to filter or group. + - Hide summarizable fact table columns—that ensures only measures can be used to summarize the fact table. ## Related content @@ -297,5 +287,5 @@ For more information related to this article, check out the following resources: - [Model relationships in Power BI Desktop](../transform-model/desktop-relationships-understand.md) - [Understand star schema and the importance for Power BI](star-schema.md) - [Relationship troubleshooting guidance](relationships-troubleshoot.md) -- Questions? [Try asking the Power BI Community](https://community.powerbi.com/) -- Suggestions? [Contribute ideas to improve Power BI](https://ideas.powerbi.com/) +- Questions? [Try asking the Fabric Community](https://community.fabric.microsoft.com/) +- Suggestions? [Contribute ideas to improve Fabric](https://ideas.fabric.microsoft.com/) diff --git a/powerbi-docs/guidance/relationships-one-to-one.md b/powerbi-docs/guidance/relationships-one-to-one.md index 6938a4c3b4..fc4c8ccd77 100644 --- a/powerbi-docs/guidance/relationships-one-to-one.md +++ b/powerbi-docs/guidance/relationships-one-to-one.md @@ -1,6 +1,6 @@ --- -title: One-to-one relationship guidance -description: Guidance for understanding, developing, and working with one-to-one model relationships in Power BI. +title: "One-to-one relationship guidance" +description: "Guidance for understanding, developing, and working with one-to-one model relationships in Power BI." author: denglishbi ms.author: daengli ms.reviewer: maroche @@ -8,137 +8,133 @@ ms.service: powerbi ms.subservice: powerbi-resource ms.topic: concept-article ms.custom: fabric-cat -ms.date: 07/25/2024 -#customer intent: As a data modeler working with Power BI Desktop, I want guidance on working with one-to-one model relationships so that I can effectively design and develop my data models. +ms.date: 12/27/2024 --- # One-to-one relationship guidance -This article targets you as a data modeler working with Power BI Desktop. It provides you with guidance on working with one-to-one model relationships. A one-to-one relationship can be created when both tables each contain a column of common and unique values. +This article targets you as a data modeler who works with Power BI Desktop. It provides you with guidance on working with one-to-one model relationships. A one-to-one relationship can be created when both tables each contain a column of common and unique values. [!INCLUDE [relationships-prerequisite-reading](includes/relationships-prerequisite-reading.md)] There are two scenarios that involve one-to-one relationships: -- [Degenerate dimensions](#degenerate-dimensions): You can derive a [degenerate dimension](star-schema.md#degenerate-dimensions) from a fact-type table. -- [Row data spans across tables](#row-data-spans-across-tables): A single business entity or subject is loaded as two (or more) model tables, possibly because their data is sourced from different data stores. This scenario can be common for dimension-type tables. For example, master product details are stored in an operational sales system, and supplementary product details are stored in a different source. +- **[Degenerate dimensions](#degenerate-dimensions)**: You can derive a [degenerate dimension](star-schema.md#degenerate-dimensions) from a fact table. +- **[Row data spans across tables](#row-data-spans-across-tables)**: A single business entity or subject is loaded as two (or more) model tables, possibly because their data is sourced from different data stores. This scenario can be common for dimension tables. For example, master product details are stored in an operational sales system, and supplementary product details are stored in a different source. - It's unusual, however, that you'd relate two fact-type tables with a one-to-one relationship. It's because both fact-type tables would need to have the same dimensionality and granularity. Also, each fact-type table would need unique columns to allow the model relationship to be created. + It's unusual, however, that you'd relate two fact tables with a one-to-one relationship. That's because both fact tables would need to have the same dimensionality and granularity. Also, each fact table would need unique columns to allow the model relationship to be created. ## Degenerate dimensions -When columns from a fact-type table are used for filtering or grouping, you can consider making them available in a separate table. This way, you separate columns used for filtering or grouping from those columns used to summarize fact rows. This separation can: +When columns from a fact table are used for filtering or grouping, you can consider making them available in a separate table. This way, you separate columns used for filtering or grouping from those columns used to summarize fact rows. This separation can: -- Reduce storage space -- Simplify model calculations -- Contribute to improved query performance -- Deliver a more intuitive **Data** pane experience to your report authors +- Reduce storage space. +- Simplify model calculations. +- Contribute to improved query performance. +- Deliver a more intuitive **Data** pane experience to your report authors. -Consider a source sales table that stores sales order details in two columns. +Consider a source table named `Sales` that stores sales order line reference details in two columns. -![Table rows for a sales table.](media/relationships-one-to-one/sales-order-rows.png) +:::image type="content" source="media/relationships-one-to-one/sales-order-rows.svg" alt-text="Diagram showing table rows for the Sales degenerate dimension table. The design is described in the following paragraph." border="false"::: -The **OrderNumber** column stores the order number, and the **OrderLineNumber** column stores a sequence of lines within the order. +The `OrderNumber` column stores the order number, and the `OrderLineNumber` column stores a sequence of lines within the order. -In the following model diagram, notice that the order number and order line number columns haven't been loaded to the **Sales** table. Instead, their values were used to create a [surrogate key](star-schema.md#surrogate-keys) column named **SalesOrderLineID**. (The key value is calculated by multiplying the order number by 1000, and then adding the order line number.) +In the following image, notice that the order number and order line number columns haven't been loaded to the `Sales` table. Instead, their values were used to create a [surrogate key](star-schema.md#surrogate-keys) column named `OrderLineNumberID`. (The key value is calculated by multiplying the order number by 1000, and then adding the order line number.) -![A model diagram contains two tables: Sales and Sales Order. A one-to-one relationship relates the SalesOrderLineID columns.](media/relationships-one-to-one/sales-order-degenerate.png) +:::image type="content" source="media/relationships-one-to-one/sales-order-degenerate.svg" alt-text="Diagram showing two tables: Sales and Sales Order. A one-to-one relationship relates the Order Line Number ID columns." border="false"::: -The **Sales Order** table provides a rich experience for report authors with three columns: **Sales Order**, **Sales Order Line**, and **Line Number**. It also includes a hierarchy. These table resources support report designs that need to filter, group by, or drill down through orders and order lines. +The `Sales Order` dimension table provides a rich experience for report authors with two columns: `Sales Order` and `Sales Order Line`. These particular columns support report designs that need to filter, group, or drill down through orders and order lines. -As the **Sales Order** table is derived from the sales data, there should be exactly the same number of rows in each table. Further, there should be matching values between each **SalesOrderLineID** column. +Because the `Sales Order` table is derived from the sales data, there should be exactly the same number of rows in each table. Further, there should be matching values between each `OrderLineNumberID` column. ## Row data spans across tables -Consider an example involving two one-to-one related dimension-type tables: **Product**, and **Product Category**. Each table represents imported data and has an **SKU** (Stock-Keeping Unit) column containing unique values. +Consider an example that involves two one-to-one related dimension tables: `Product` and `Product Category`. Each table represents imported data and has a `SKU` (stock-keeping unit) column that contains unique values. Here's a partial model diagram of the two tables. -![A model diagram contains two tables. The design is described in the following paragraph.](media/relationships-one-to-one/product-to-product-category.png) +:::image type="content" source="media/relationships-one-to-one/product-to-product-category.svg" alt-text="Diagram showing a model that contains two tables where row data spans across tables. The design is described in the following paragraph." border="false"::: -The first table is named **Product**, and it contains three columns: **Color**, **Product**, and **SKU**. The second table is named **Product Category**, and it contains two columns: **Category**, and **SKU**. A one-to-one relationship relates the two **SKU** columns. The relationship filters in both directions, which is always the case for one-to-one relationships. +The first table is named `Product`, and it contains three columns: `Color`, `Product`, and `SKU`. The second table is named `Product Category`, and it contains two columns: `Category` and `SKU`. A one-to-one relationship relates the two `SKU` columns. The relationship filters in both directions, which is always the case for one-to-one relationships. -To help describe how the relationship filter propagation works, the model diagram has been modified to reveal the table rows. All examples in this article are based on this data. +To help describe how the relationship filter propagation works, the following image reveals some table rows. All examples in this article are based on this data. -> [!NOTE] -> It's not possible to display table rows in the Power BI Desktop model diagram. It's done in this article to support the discussion with clear examples. - -![The model diagram now reveals the table rows. The row details are described in the following paragraph.](media/relationships-one-to-one/product-to-product-category-2.png) +:::image type="content" source="media/relationships-one-to-one/product-to-product-category-2.svg" alt-text="Diagram showing the Product and Product Category tables and some rows of data. The row details are described in the following paragraph." border="false"::: The row details for the two tables are described in the following bulleted list: -- The **Product** table has three rows: - - **SKU** CL-01, **Product** T-shirt, **Color** Green - - **SKU** CL-02, **Product** Jeans, **Color** Blue - - **SKU** AC-01, **Product** Hat, **Color** Blue -- The **Product Category** table has two rows: - - **SKU** CL-01, **Category** Clothing - - **SKU** AC-01, **Category** Accessories - -Notice that the **Product Category** table doesn't include a row for the product SKU CL-02. We'll discuss the consequences of this missing row later in this article. - -In the **Data** pane, report authors will find product-related fields in two tables: **Product** and **Product Category**. +- The `Product` table has three rows: + - `SKU` **CL-01**, `Product` **T-shirt**, `Color` **Green** + - `SKU` **CL-02**, `Product` **Jeans**, `Color` **Blue** + - `SKU` **AC-01**, `Product` **Hat**, `Color` **Blue** +- The `Product Category` table has two rows: + - `SKU` **CL-01**, `Category` **Clothing** + - `SKU` **AC-01**, `Category` **Accessories** -![The Data pane shows both tables expanded, and the columns are listed as fields with Product and Product category called out.](media/relationships-one-to-one/product-to-product-category-data-pane.png) +Notice that the `Product Category` table doesn't include a row for the product SKU **CL-02**. We'll discuss the consequences of this missing row later in this article. -Let's see what happens when fields from both tables are added to a table visual. In this example, the **SKU** column is sourced from the **Product** table. +In the **Data** pane, report authors find product-related fields in two tables: `Product` and `Product Category`. Let's see what happens when fields from both tables are added to a table visual. In this example, the `SKU` column is sourced from the `Product` table. -![A table visual includes four columns: SKU, Product, Color, and Category. The Category value for product SKU CL-02 is BLANK.](media/relationships-one-to-one/product-to-product-category-table-visual.png) +:::image type="content" source="media/relationships-one-to-one/product-to-product-category-consequences.svg" alt-text="Diagram showing the Data pane with two tables, and a table visual that includes four columns. The Category value for product SKU CL-02 is BLANK." border="false"::: -Notice that the **Category** value for product SKU CL-02 is BLANK. It's because there's no row in the **Product Category** table for this product. +Notice that the `Category` value for product SKU **CL-02** is BLANK. That's because there's no corresponding row in the `Product Category` table for this product. ### Recommendations -When possible, we recommend you avoid creating one-to-one model relationships when row data spans across model tables. It's because this design can: +When possible, we recommend you avoid creating one-to-one model relationships when row data spans across model tables. That's because this design can: - Contribute to **Data** pane clutter, listing more tables than necessary. - Make it difficult for report authors to find related fields, because they're distributed across multiple tables. -- Limit the ability to create hierarchies, as their levels must be based on columns from the _same table_. +- Limit the ability to create hierarchies, as their levels must be based on columns from the same table. - Produce unexpected results when there isn't a complete match of rows between the tables. -Specific recommendations differ depending on whether the one-to-one relationship is _intra source group_ or _cross source group_. For more information about relationship evaluation, see [Model relationships in Power BI Desktop (Relationship evaluation)](../transform-model/desktop-relationships-understand.md#relationship-evaluation). +Specific recommendations differ depending on whether the one-to-one relationship is _intra source group_ or _cross source group_. For more information about relationship evaluation, see [Model relationships in Power BI Desktop](../transform-model/desktop-relationships-understand.md#relationship-evaluation). ### Intra source group one-to-one relationship -When a one-to-one _intra source group_ relationship exists between tables, we recommend consolidating the data into a single model table. It's done by merging the Power Query queries. +When a one-to-one _intra source group_ relationship exists between tables, we recommend consolidating the data into a single model table. You can do that by merging the Power Query queries. -The following steps present a methodology to consolidate and model the one-to-one related data: +The following steps present a methodology to consolidate and model the one-to-one related data. -1. **Merge queries**: When [combining the two queries](../connect-data/desktop-shape-and-combine-data.md#combine-queries), give consideration to the completeness of data in each query. If one query contains a complete set of rows (like a master list), merge the other query with it. Configure the merge transformation to use a _left outer join_, which is the default join type. This join type ensures you'll keep all rows of the first query, and supplement them with any matching rows of the second query. Expand all required columns of the second query into the first query. -2. **Disable query load**: Be sure to [disable the load](import-modeling-data-reduction.md#disable-power-query-query-load) of the second query. This way, it won't load its result as a model table. This configuration reduces the data model storage size, and helps to unclutter the **Data** pane. +1. **Merge queries**: When [combining the two queries](../connect-data/desktop-shape-and-combine-data.md#combine-queries), give consideration to the completeness of data in each query. If one query contains a complete set of rows (like a master list), merge the other query with it. Set the merge transformation to use a _left outer join_, which is the default join type. This join type ensures you'll keep all rows of the first query, and supplement them with any matching rows of the second query. Expand all required columns of the second query into the first query. - In our example, report authors now find a single table named **Product** in the **Data** pane. It contains all product-related fields. + :::image type="content" source="media/relationships-one-to-one/product-to-product-category-consolidated.svg" alt-text="Diagram showing data consolidated to a single Product dimension table." border="false"::: - ![The Data pane shows both tables expanded, and the columns are listed as fields with Product called out.](media/relationships-one-to-one/product-to-product-category-data-pane-consolidated.png) -3. **Replace missing values**: If the second query has unmatched rows, null values appear in the columns introduced from it. When appropriate, consider replacing null values with a token value. Replacing missing values is especially important when report authors filter or group by the column values, as BLANKs could appear in report visuals. +1. **Disable query load**: Be sure to [disable the load](import-modeling-data-reduction.md#disable-power-query-query-load) of the second query. This way, it won't load its result as a model table. This configuration reduces the data model storage size, and helps to unclutter the **Data** pane. - In the following table visual, notice that the category for product SKU CL-02 now reads _[Undefined]_. In the query, null categories were replaced with this token text value. + In our example, report authors now find a single table named `Product` in the **Data** pane. It contains all product-related fields. - ![A table visual includes four columns: SKU, Product, Color, and Category. The Category value for product SKU CL-02 is now labeled "Undefined".](media/relationships-one-to-one/product-to-product-category-table-visual-null-replaced.png) +1. **Replace missing values**: If the second query has unmatched rows, null values appear in the columns introduced from it. When appropriate, consider replacing null values with a token value. Replacing missing values is especially important when report authors filter or group by the column values, as BLANKs could appear in report visuals. -4. **Create hierarchies**: If relationships exist _between the columns_ of the now-consolidated table, consider creating hierarchies. This way, report authors will quickly identify opportunities for report visual drilling. + In the following image, notice that the category for product SKU **CL-02** now reads **[Undefined]**. In the query, null categories were replaced with this token text value. + + :::image type="content" source="media/relationships-one-to-one/product-to-product-category-consolidated-consequences.svg" alt-text="Diagram showing the Data pane for the Product table. It also shows a table visual with four columns. The Category value for product SKU CL-02 is now labeled Undefined." border="false"::: - In our example, report authors now can use a hierarchy that has two levels: **Category** and **Product**. +1. **Create hierarchies**: If relationships exist _between the columns_ of the now-consolidated table, consider creating hierarchies. This way, report authors will quickly identify opportunities for report visual drilling. - ![The Data pane shows both tables expanded, and the columns are listed as fields with Products called out.](media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-with-hierarchy.png) + In our example, report authors now can use a hierarchy that has two levels: `Category` and `Product`. + + :::image type="content" source="media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-with-hierarchy.svg" alt-text="Diagram showing the Data pane. The Product table includes the Products hierarchy." border="false"::: If you like how separate tables help organize your fields, we still recommend consolidating into a single table. You can still organize your fields, but by using _display folders_ instead. -In our example, report authors can find the **Category** field within the **Marketing** display folder. +In our example, report authors can find the `Category` field within the `Marketing` display folder. -![The Data pane shows the Category field within a display folder named Marketing.](media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-display-folder.png) +:::image type="content" source="media/relationships-one-to-one/product-to-product-category-data-pane-consolidated-into-display-folder.svg" alt-text="Diagram showing the Data pane where the Category field is within a display folder named Marketing." border="false"::: Should you still decide to define one-to-one intra source group relationships in your model, when possible, ensure there are matching rows in the related tables. As a one-to-one intra source group relationship is evaluated as a [regular relationship](../transform-model/desktop-relationships-understand.md#regular-relationships), data integrity issues could surface in your report visuals as BLANKs. (You can see an example of a BLANK grouping in the first table visual presented in this article.) ### Cross source group one-to-one relationship -When a one-to-one _cross source group_ relationship exists between tables, there's no alternative model design—unless you pre-consolidate the data in your data sources. Power BI will evaluate the one-to-one model relationship as a [limited relationship](../transform-model/desktop-relationships-understand.md#limited-relationships). Therefore, take care to ensure there are matching rows in the related tables, as unmatched rows will be eliminated from query results. +When a one-to-one _cross source group_ relationship exists between tables, there's no alternative model design—unless you pre-consolidate the data in your data source. Power BI will evaluate the one-to-one model relationship as a [limited relationship](../transform-model/desktop-relationships-understand.md#limited-relationships). Therefore, take care to ensure there are matching rows in the related tables, as unmatched rows are eliminated from query results. + +:::image type="content" source="media/relationships-one-to-one/product-to-product-category-cross-source.svg" alt-text="Diagram showing a cross source group one-to-one relationship, which is a limited relationship." border="false"::: Let's see what happens when fields from both tables are added to a table visual, and a limited relationship exists between the tables. -![A table visual includes four columns: SKU, Product, Color, and Category. The table has two rows only.](media/relationships-one-to-one/product-to-product-category-table-visual-weak-relationship.png) +:::image type="content" source="media/relationships-one-to-one/product-to-product-category-table-visual-weak-relationship.svg" alt-text="Diagram showing two table visuals, which are described in the following paragraph." border="false"::: -The table displays two rows only. Product SKU CL-02 is missing because there's no matching row in the **Product Category** table. +The first table visual, which uses a cross-source group relationship, displays two rows only. Product SKU **CL-02** is missing because there's no matching row in the `Product Category` table. The second table visual, based on a single consolidated table in the model, displays three rows. ## Related content @@ -147,5 +143,5 @@ For more information related to this article, check out the following resources: - [Model relationships in Power BI Desktop](../transform-model/desktop-relationships-understand.md) - [Understand star schema and the importance for Power BI](star-schema.md) - [Relationship troubleshooting guidance](relationships-troubleshoot.md) -- Questions? [Try asking the Power BI Community](https://community.powerbi.com/) -- Suggestions? [Contribute ideas to improve Power BI](https://ideas.powerbi.com/) +- Questions? [Try asking the Fabric Community](https://community.fabric.microsoft.com/) +- Suggestions? [Contribute ideas to improve Fabric](https://ideas.fabric.microsoft.com/) diff --git a/powerbi-docs/guidance/relationships-troubleshoot.md b/powerbi-docs/guidance/relationships-troubleshoot.md index 5b8888d0f6..ad1a214fc2 100644 --- a/powerbi-docs/guidance/relationships-troubleshoot.md +++ b/powerbi-docs/guidance/relationships-troubleshoot.md @@ -1,6 +1,6 @@ --- -title: Relationship troubleshooting guidance -description: Guidance for troubleshooting Power BI data model relationship issues. +title: "Relationship troubleshooting guidance" +description: "Guidance for troubleshooting Power BI data model relationship issues." author: denglishbi ms.author: daengli ms.reviewer: maroche @@ -8,18 +8,18 @@ ms.service: powerbi ms.subservice: powerbi-resource ms.topic: troubleshooting ms.custom: fabric-cat -ms.date: 10/14/2023 +ms.date: 12/27/2024 --- # Relationship troubleshooting guidance -This article targets you as a data modeler working with Power BI Desktop. It provides guidance on how to troubleshoot specific issues that you might encounter when developing models and reports. +This article targets you as a data modeler who works with Power BI Desktop. It provides guidance on how to troubleshoot specific issues that you might encounter when developing models and reports. [!INCLUDE [relationships-prerequisite-reading](includes/relationships-prerequisite-reading.md)] ## Troubleshooting -When a report visual is set up to use fields from two (or more) tables, and it doesn't present the correct result (or any result), it's possible that the issue is related to model relationships. +When a report visual is set up to use fields from two (or more) tables, and it doesn't present the correct result (or any result), it's possible that the issue is related to the model relationships. In this case, here's a general troubleshooting checklist to follow. You can progressively work through the checklist until you identify the issue(s). @@ -38,13 +38,13 @@ In this case, here's a general troubleshooting checklist to follow. You can prog Here's a list of issues and their possible reasons. -| **Issue** | **Possible reason(s)** | +| Issue | Possible reason(s) | |---|---| | The visual displays no result | • The model is yet to be loaded with data.
• No data exists within the filter context.
• Row-level security (RLS) is enforced.
• Relationships aren't propagating between tables—_follow checklist above_.
• RLS is enforced, but a bi-directional relationship isn't enabled to propagate—see [Row-level security (RLS) with Power BI Desktop](/fabric/security/service-admin-row-level-security). | | The visual displays the same value for each grouping | • Relationships don't exist.
• Relationships aren't propagating between tables—_follow checklist above_. | -| The visual displays results, but they aren't correct | • Visual is incorrectly set up.
• Measure calculation logic is incorrect.
• Model data needs to be refreshed.
• Source data is incorrect.
• Relationship columns are incorrectly related (for example, **ProductID** column maps to **CustomerID**).
• It's a relationship between two DirectQuery tables, and the "one"-side column of a relationship contains duplicate values. | -| BLANK groupings or slicer/filter items appear, and the source columns don't contain BLANKs | • It's a regular relationship, and "many"-side column contain values not stored in the "one"-side column—see [Model relationships in Power BI Desktop (Regular relationships)](/power-bi/transform-model/desktop-relationships-understand#regular-relationships).
• It's a regular one-to-one relationship, and related columns contain BLANKs—see [Model relationships in Power BI Desktop (Regular relationships)](/power-bi/transform-model/desktop-relationships-understand#regular-relationships).
• An inactive relationship "many"-side column stores BLANKs, or has values not stored on the "one" side. | -| The visual is missing data | • Incorrect/unexpected filters are applied.
• RLS is enforced.
• It's a limited relationship, and there are BLANKs in related columns, or data integrity issues—see [Model relationships in Power BI Desktop (limited relationships)](/power-bi/transform-model/desktop-relationships-understand#limited-relationships).
• It's a relationship between two DirectQuery tables, the relationship is set to [assume referential integrity](/power-bi/transform-model/desktop-relationships-understand#assume-referential-integrity), but there are data integrity issues (mismatched values in related columns). | +| The visual displays results, but they aren't correct | • Visual is incorrectly set up.
• Measure calculation logic is incorrect.
• Model data needs to be refreshed.
• Source data is incorrect.
• Relationship columns are incorrectly related (for example, the `ProductID` column maps to the `CustomerID` column).
• It's a relationship between two DirectQuery tables, and the "one"-side column of a relationship contains duplicate values. | +| BLANK groupings or slicer/filter items appear, and the source columns don't contain BLANKs | • It's a regular relationship, and "many"-side column contain values not stored in the "one"-side column—see [Model relationships in Power BI Desktop](/power-bi/transform-model/desktop-relationships-understand#regular-relationships).
• It's a regular one-to-one relationship, and related columns contain BLANKs—see [Model relationships in Power BI Desktop](/power-bi/transform-model/desktop-relationships-understand#regular-relationships).
• An inactive relationship "many"-side column stores BLANKs, or has values not stored on the "one" side. | +| The visual is missing data | • Incorrect/unexpected filters are applied.
• RLS is enforced.
• It's a limited relationship, and there are BLANKs in related columns, or data integrity issues—see [Model relationships in Power BI Desktop](/power-bi/transform-model/desktop-relationships-understand#limited-relationships).
• It's a relationship between two DirectQuery tables, the relationship is set to [assume referential integrity](/power-bi/transform-model/desktop-relationships-understand#assume-referential-integrity), but there are data integrity issues (mismatched values in related columns). | | RLS isn't correctly enforced | • Relationships aren't propagating between tables—_follow checklist above_.
• RLS is enforced, but a bi-directional relationship isn't enabled to propagate—see [Row-level security (RLS) with Power BI Desktop](/fabric/security/service-admin-row-level-security). | ## Related content @@ -52,5 +52,5 @@ Here's a list of issues and their possible reasons. For more information related to this article, check out the following resources: - [Model relationships in Power BI Desktop](/power-bi/transform-model/desktop-relationships-understand) -- Questions? [Try asking the Power BI Community](https://community.powerbi.com/) -- Suggestions? [Contribute ideas to improve Power BI](https://ideas.powerbi.com/) +- Questions? [Try asking the Fabric Community](https://community.fabric.microsoft.com/) +- Suggestions? [Contribute ideas to improve Fabric](https://ideas.fabric.microsoft.com/) diff --git a/powerbi-docs/guidance/star-schema.md b/powerbi-docs/guidance/star-schema.md index b5ef6fc759..da04c4bdd2 100644 --- a/powerbi-docs/guidance/star-schema.md +++ b/powerbi-docs/guidance/star-schema.md @@ -8,7 +8,7 @@ ms.service: powerbi ms.subservice: powerbi-resource ms.topic: conceptual ms.custom: fabric-cat -ms.date: 10/29/2024 +ms.date: 12/27/2024 --- # Understand star schema and the importance for Power BI @@ -27,8 +27,13 @@ This article targets Power BI Desktop data modelers. It describes star schema de _Star schema_ is a mature modeling approach widely adopted by relational data warehouses. It requires modelers to classify their model tables as either _dimension_ or _fact_. -- **Dimension tables** describe business entities—the _things_ you model. Entities can include products, people, places, and concepts including time itself. The most consistent table you'll find in a star schema is a date dimension table. A dimension table contains a key column (or columns) that acts as a unique identifier, and other columns. Other columns support filtering and grouping your data. -- **Fact tables** store observations or events, and can be sales orders, stock balances, exchange rates, temperatures, and more. A fact table contains dimension key columns that relate to dimension tables, and numeric measure columns. The dimension key columns determine the _dimensionality_ of a fact table, while the dimension key values determine the _granularity_ of a fact table. For example, consider a fact table designed to store sale targets that has two dimension key columns `Date` and `ProductKey`. It's easy to understand that the table has two dimensions. The granularity, however, can't be determined without considering the dimension key values. In this example, consider that the values stored in the `Date` column are the first day of each month. In this case, the granularity is at month-product level. +### Dimension tables + +_Dimension tables_ describe business entities—the _things_ you model. Entities can include products, people, places, and concepts including time itself. The most consistent table you'll find in a star schema is a date dimension table. A dimension table contains a key column (or columns) that acts as a unique identifier, and other columns. Other columns support filtering and grouping your data. + +### Fact tables + +_Fact tables_ store observations or events, and can be sales orders, stock balances, exchange rates, temperatures, and more. A fact table contains dimension key columns that relate to dimension tables, and numeric measure columns. The dimension key columns determine the _dimensionality_ of a fact table, while the dimension key values determine the _granularity_ of a fact table. For example, consider a fact table designed to store sale targets that has two dimension key columns `Date` and `ProductKey`. It's easy to understand that the table has two dimensions. The granularity, however, can't be determined without considering the dimension key values. In this example, consider that the values stored in the `Date` column are the first day of each month. In this case, the granularity is at month-product level. Generally, dimension tables contain a relatively small number of rows. Fact tables, on the other hand, can contain a large number of rows and continue to grow over time. @@ -169,7 +174,7 @@ It's a good design practice to include a hierarchy that allows visuals to drill A _role-playing dimension_ is a dimension that can filter related facts differently. For example, at Adventure Works the date dimension table has three relationships to the reseller sales facts. The same dimension table can be used to filter the facts by order date, ship date, or delivery date. -:::image type="content" source="media/star-schema/role-playing-dimensions.svg" alt-text="Diagram showing a conceptual example of a single role-playing dimension and relationships. The Date table has two relationships to the fact table for order date and ship date." border="false"::: +:::image type="content" source="media/star-schema/role-playing-dimensions.svg" alt-text="Diagram showing a conceptual example of a single role-playing dimension and relationships. The Date table has two relationships to the fact table." border="false"::: In a data warehouse, the accepted design approach is to define a single date dimension table. At query time, the "role" of the date dimension is established by which fact column you use to join the tables. For example, when you analyze sales by order date, the table join relates to the reseller sales order date column. @@ -205,7 +210,7 @@ The design objective of a junk dimension is to consolidate many _small_ dimensio A junk dimension table is typically the Cartesian product of all dimension attribute members, with a [surrogate key](#surrogate-keys) column to uniquely identify each row. You can build the dimension in a data warehouse, or by using Power Query to create a query that performs [full outer query joins](/powerquery-m/table-join), then adds a surrogate key (index column). -:::image type="content" source="media/star-schema/junk-dimension.svg" alt-text="Diagram showing an example of a junk dimension table. Order Status has three states while Delivery Status has two states. The junk dimension table stores all six combinations of the two statuses." border="false"::: +:::image type="content" source="media/star-schema/junk-dimension.svg" alt-text="Diagram showing an example of a junk dimension table. Order Status has three states while Delivery Status has two states." border="false"::: You load this query to the model as a dimension table. You also need to merge this query with the fact query so the index column is loaded to the model to support the creation of a "one-to-many" model relationship. @@ -229,7 +234,7 @@ A more compelling use of a factless fact table is to store relationships between For example, consider that salespeople can be assigned to one _or more_ sales regions. The bridging table would be designed as a factless fact table consisting of two columns: salesperson key and region key. Duplicate values can be stored in both columns. -:::image type="content" source="media/star-schema/factless-fact-table.svg" alt-text="Diagram showing a factless fact table bridging Salesperson and Region dimensions. The factless fact table comprises two columns, which are the dimension keys." border="false"::: +:::image type="content" source="media/star-schema/factless-fact-table.svg" alt-text="Diagram showing a factless fact table bridging Salesperson and Region dimensions. The factless fact table comprises two columns." border="false"::: This many-to-many design approach is well documented, and it can be achieved without a bridging table. However, the bridging table approach is considered the best practice when relating two dimensions. For more information, see [Many-to-many relationship guidance (Relate two dimension-type tables)](relationships-many-to-many.md#relate-many-to-many-dimensions).