多対多のリレーションシップのガイダンスMany-to-many relationship guidance

この記事は、Power BI Desktop を操作するデータ モデラーを対象としています。This article targets you as a data modeler working with Power BI Desktop. 3 つの異なる多対多モデリング シナリオについて説明します。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.

注意

この記事には、モデル リレーションシップの概要は含まれません。An introduction to model relationships is not covered in this article. リレーションシップやそのプロパティ、あるいはその構成方法に完全には慣れていない場合は、まず、Power BI Desktop でのモデル リレーションシップに関する記事をお読みになることをお勧めします。If you're not completely familiar with relationships, their properties or how to configure them, we recommend that you first read the Model relationships in Power BI Desktop article.

スター スキーマの設計について理解していることも重要です。It's also important that you have an understanding of star schema design. 詳細については、「スター スキーマと Power BI での重要性を理解する」を参照してください。For more information, see Understand star schema and the importance for Power BI.

実際には、3 つの多対多のシナリオがあります。There are, in fact, three many-to-many scenarios. これらは、次のことが必要な場合に発生する可能性があります。They can occur when you're required to:

多対多ディメンションを関連付けるRelate many-to-many dimensions

例を使って、最初の多対多シナリオの種類について考えてみましょう。Let's consider the first many-to-many scenario type with an example. 従来のシナリオでは、銀行の顧客と銀行口座という 2 つのエンティティが関連付けられます。The classic scenario relates two entities: bank customers and bank accounts. 顧客は複数の口座を持つことができ、口座に対して複数の顧客が存在できるとします。Consider that customers can have multiple accounts, and accounts can have multiple customers. 1 つの口座に対して複数の顧客が存在する場合、それらは一般に "共同口座名義人" と呼ばれます。When an account has multiple customers, they're commonly called joint account holders.

これらのエンティティのモデリングは簡単です。Modeling these entities is straight forward. 1 つのディメンションの種類のテーブルに口座が格納され、もう 1 つのディメンションの種類のテーブルには顧客が格納されます。One dimension-type table stores accounts, and another dimension-type table stores customers. ディメンションの種類のテーブルの特性と同様、各テーブルには ID 列があります。As is characteristic of dimension-type tables, there's an ID column in each table. 2 つのテーブル間のリレーションシップをモデリングするには、3 番目のテーブルが必要です。To model the relationship between the two tables, a third table is required. このテーブルは、一般に "ブリッジング テーブル" と呼ばれます。This table is commonly referred to as a bridging table. この例では、顧客と口座の関連付けごとに 1 つの行を格納することを目的としています。In this example, it's purpose is to store one row for each customer-account association. 興味深いことに、このテーブルに ID 列のみが含まれている場合は、"ファクトレス ファクト テーブル" と呼ばれます。Interestingly, when this table only contains ID columns, it's called a factless fact table.

3 つのテーブルのシンプルなモデル図を以下に示します。Here's a simplistic model diagram of the three tables.

3 つのテーブルを含むモデルを示す図。

最初のテーブルには Account という名前が付けられ、次の 2 つの列が含まれています: AccountIDAccountThe first table is named Account, and it contains two columns: AccountID and Account. 2 番目のテーブルには AccountCustomer という名前が付けられ、次の 2 つの列が含まれています: AccountIDCustomerIDThe second table is named AccountCustomer, and it contains two columns: AccountID and CustomerID. 3 番目のテーブルには Customer という名前が付けられ、次の 2 つの列が含まれています: CustomerIDCustomerThe third table is named Customer, and it contains two columns: CustomerID and Customer. どのテーブル間にもリレーションシップは存在しません。Relationships don't exist between any of the tables.

テーブルを関連付けるために、2 つの一対多リレーションシップが追加されます。Two one-to-many relationships are added to relate the tables. 関連テーブルの更新されたモデル図を以下に示します。Here's an updated model diagram of the related tables. Transaction という名前のファクトの種類のテーブルが追加されました。A fact-type table named Transaction has been added. これには口座取引が記録されています。It records account transactions. ブリッジング テーブルとすべての ID 列が非表示になりました。The bridging table and all ID columns have been hidden.

モデルに含まれるテーブルが 4 つになったことを示す図。

リレーションシップ フィルターの伝達のしくみを説明するのに役立つように、モデル図が変更されてテーブル行が表示されました。To help describe how the relationship filter propagation works, the model diagram has been modified to reveal the table rows.

注意

Power BI Desktop モデル図にテーブル行を表示することはできません。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.

モデルでテーブル行が表示されるようになったことを示す図。

4 つのテーブルの行の詳細については、次の箇条書きで説明します。The row details for the four tables are described in the following bulleted list:

  • Account テーブルには、次の 2 つの行があります。The Account table has two rows:
    • AccountID の 1 は Account-01 用ですAccountID 1 is for Account-01
    • AccountID の 2 は Account-02 用ですAccountID 2 is for Account-02
  • Customer テーブルには、次の 2 つの行があります。The Customer table has two rows:
    • CustomerID の 91 は Customer-91 用ですCustomerID 91 is for Customer-91
    • CustomerID の 92 は Customer-92 用ですCustomerID 92 is for Customer-92
  • AccountCustomer テーブルには、次の 3 つの行があります。The AccountCustomer table has three rows:
    • AccountID の 1 は、CustomerID の 91 に関連付けられていますAccountID 1 is associated with CustomerID 91
    • AccountID の 1 は、CustomerID の 92 に関連付けられていますAccountID 1 is associated with CustomerID 92
    • AccountID の 2 は、CustomerID の 92 に関連付けられていますAccountID 2 is associated with CustomerID 92
  • Transaction テーブルには、次の 3 つの行があります。The Transaction table has three rows:
    • Date は 2019 年 1 月 1 日、AccountID は 1、Amount は 100 ですDate January 1 2019, AccountID 1, Amount 100
    • Date は 2019 年 2 月 2 日、AccountID は 2、Amount は 200 ですDate February 2 2019, AccountID 2, Amount 200
    • Date は 2019 年 3 月 3 日、AccountID は 1、Amount は -25 ですDate March 3 2019, AccountID 1, Amount -25

モデルにクエリを実行するとどうなるかを見てみましょう。Let's see what happens when the model is queried.

Transaction テーブルから Amount 列を集計する 2 つのビジュアルを以下に示します。Below are two visuals that summarize the Amount column from the Transaction table. 最初のビジュアルでは口座別にグループ化されているため、Amount 列の合計は "口座残高" を表します。The first visual groups by account, and so the sum of the Amount columns represents the account balance. 2 番目のビジュアルでは顧客別にグループ化されているため、Amount 列の合計は "顧客残高" を表します。The second visual groups by customer, and so the sum of the Amount columns represents the customer balance.

2 つのレポート ビジュアルが左右に並べて表示されている図。

最初のビジュアルには Account Balance というタイトルが付いており、次の 2 つの列があります: AccountAmountThe first visual is titled Account Balance, and it has two columns: Account and Amount. これには次の結果が表示されています。It displays the following result:

  • Account-01 の残額は 75 ですAccount-01 balance amount is 75
  • Account-02 の残額は 200 ですAccount-02 balance amount is 200
  • 合計は 275 ですThe total is 275

2 番目のビジュアルには Customer Balance というタイトルが付いており、次の 2 つの列があります: CustomerAmountThe second visual is titled Customer Balance, and it has two columns: Customer and Amount. これには次の結果が表示されています。It displays the following result:

  • Customer-91 の残額は 275 ですCustomer-91 balance amount is 275
  • Customer-92 の残額は 275 ですCustomer-92 balance amount is 275
  • 合計は 275 ですThe total is 275

テーブル行と Account Balance ビジュアルをひとめ見れば、各口座と合計額の結果が正しいことがわかります。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. これは、各口座のグループ化によって、その口座の Transaction テーブルにフィルターが伝達されるためです。It's because each account grouping results in a filter propagation to the Transaction table for that account.

しかし、Customer Balance ビジュアルでは、何かが正しくないように見えます。However, something doesn't appear correct with the Customer Balance visual. Customer Balance の各顧客の残高が、合計残高と同じになっています。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. Transaction テーブルへのフローがありません。It's not flowing all the way to the Transaction table.

Customer テーブルから Transaction テーブルへのリレーションシップのフィルター方向をたどってください。Follow the relationship filter directions from the Customer table to the Transaction table. AccountAccountCustomer テーブル間のリレーションシップが間違った方向に伝達されているのは明らかです。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.

モデルが更新されたことを示す図。

同じ 2 つのレポート ビジュアルが左右に並べて表示されている図。

予想どおり、Account Balance ビジュアルに変更はありませんでした。As expected, there has been no change to the Account Balance visual.

しかし、Customer Balance ビジュアルでは、次の結果が表示されるようになりました。The Customer Balance visuals, however, now displays the following result:

  • Customer-91 の残額は 75 ですCustomer-91 balance amount is 75
  • Customer-92 の残額は 275 ですCustomer-92 balance amount is 275
  • 合計は 275 ですThe total is 275

これで、Customer Balance ビジュアルで正しい結果が表示されるようになりました。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. 次のように質問するかもしれません: "Customer-91Customer-92 の合計残高が 350 (75 + 275) に等しくないのはなぜか? "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:

  • 多対多の関連エンティティをそれぞれモデル テーブルとして追加し、一意識別子 (ID) 列が確実に含まれるようにする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
  • 3 つのテーブル間に一対多リレーションシップを作成するCreate one-to-many relationships between the three tables
  • フィルター伝達がファクトの種類のテーブルまで続くように、1 つの双方向リレーションシップを構成するConfigure one bi-directional relationship to allow filter propagation to continue to the fact-type tables
  • ID 値が欠落していることが適切でない場合は、ID 列の Is Nullable プロパティを FALSE に設定する。これで、欠落値が発生した場合に、データ更新が失敗するようになります。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)
  • レポートに適さない ID 列をすべて非表示にする (ID が代理キーである場合など)Hide any ID columns that aren't suitable for reporting (for example, when IDs are surrogate keys)
  • ID 列を表示したままにすることが妥当である場合は、リレーションシップの "一" 側にあることを確認する。つまり、常に "多" 側の列を非表示にします。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

多対多ディメンションの種類のテーブルを直接関連付けることはお勧めしません。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. これは広く受け入れられている設計方法ですが、そのディメンションの種類のテーブルには ID 列があります。It's a well-accepted design practice, however, that dimension-type tables have an ID column. ディメンションの種類のテーブルでは常に、リレーションシップの "一" 側として ID 列を使用する必要があります。Dimension-type tables should always use the ID column as the "one" side of a relationship.

多対多ファクトを関連付けるRelate many-to-many facts

2 番目の多対多シナリオの種類には、2 つのファクトの種類のテーブルの関連付けが含まれます。The second many-to-many scenario type involves relating two fact-type tables. 2 つのファクトの種類のテーブルを直接関連付けることができます。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.

次の 2 つのファクトの種類のテーブルを含む例を考えてみましょう: OrderFulfillmentLet's consider an example that involves two fact-type tables: Order and Fulfillment. Order テーブルには注文明細行ごとに 1 行が含まれており、Fulfillment テーブルには、注文明細行ごとに 0 個以上の行を含めることができます。The Order table contains one row per order line, and the Fulfillment table can contains zero or more rows per order line. Order テーブル内の行は、販売注文を表します。Rows in the Order table represent sales orders. Fulfillment テーブル内の行は、出荷された注文品目を表します。Rows in the Fulfillment table represent order items that have been shipped. 多対多リレーションシップでは、2 つの OrderID 列が関連付けられ、フィルターは Order テーブルからのみ伝達されます (OrderFulfillment をフィルター処理)。A many-to-many relationship relates the two OrderID columns, with filter propagation only from the Order table (Order filters Fulfillment).

2 つのテーブルを含むモデルを示す図: Order と Fulfillment。

両方のテーブルでの重複する OrderID 値の格納をサポートするために、リレーションシップ カーディナリティが多対多に設定されています。The relationship cardinality is set to many-to-many to support storing duplicate OrderID values in both tables. Order テーブルでは、重複する OrderID 値が存在できます。これは、1 つの注文に複数の行を含めることができるためです。In the Order table, duplicate OrderID values can exist because an order can have multiple lines. Fulfillment テーブルでは、重複する OrderID 値が存在できます。これは、注文に複数の行が含まれる可能性があり、注文明細行が多数の出荷で満たせるためです。In the Fulfillment table, duplicate OrderID values can exist because orders may have multiple lines, and order lines can be fulfilled by many shipments.

次は、テーブル行を見てみましょう。Let's now take a look at the table rows. Fulfillment テーブルでは、注文明細行を複数の出荷で満たせることに注目してください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.)

モデルでテーブル行が表示されるようになったことを示す図。

2 つのテーブルの行の詳細については、次の箇条書きで説明します。The row details for the two tables are described in the following bulleted list:

  • Order テーブルには、以下の 5 つの行があります。The Order table has five rows:
    • OrderDate は 2019 年 1 月 1 日、OrderID は 1、OrderLine は 1、ProductID は Prod-A、OrderQuantity は 5、Sales は 50 ですOrderDate January 1 2019, OrderID 1, OrderLine 1, ProductID Prod-A, OrderQuantity 5, Sales 50
    • OrderDate は 2019 年 1 月 1 日、OrderID は 1、OrderLine は 2、ProductID は Prod-B、OrderQuantity は 10、Sales は 80 ですOrderDate January 1 2019, OrderID 1, OrderLine 2, ProductID Prod-B, OrderQuantity 10, Sales 80
    • OrderDate は 2019 年 2 月 2 日、OrderID は 2、OrderLine は 1、ProductID は Prod-B、OrderQuantity は 5、Sales は 40 ですOrderDate February 2 2019, OrderID 2, OrderLine 1, ProductID Prod-B, OrderQuantity 5, Sales 40
    • OrderDate は 2019 年 2 月 2 日、OrderID は 2、OrderLine は 2、ProductID は Prod-C、OrderQuantity は 1、Sales は 20 ですOrderDate February 2 2019, OrderID 2, OrderLine 2, ProductID Prod-C, OrderQuantity 1, Sales 20
    • OrderDate は 2019 年 3 月 3 日、OrderID は 3、OrderLine は 1、ProductID は Prod-C、OrderQuantity は 5、Sales は 100 ですOrderDate March 3 2019, OrderID 3, OrderLine 1, ProductID Prod-C, OrderQuantity 5, Sales 100
  • Fulfillment テーブルには、次の 4 つの行があります。The Fulfillment table has four rows:
    • FulfillmentDate は 2019 年 1 月 1 日、FulfillmentID は 50、OrderID は 1、OrderLine は 1、FulfillmentQuantity は 2 ですFulfillmentDate January 1 2019, FulfillmentID 50, OrderID 1, OrderLine 1, FulfillmentQuantity 2
    • FulfillmentDate は 2019 年 2 月 2 日、FulfillmentID は 51、OrderID は 2、OrderLine は 1、FulfillmentQuantity は 5 ですFulfillmentDate February 2 2019, FulfillmentID 51, OrderID 2, OrderLine 1, FulfillmentQuantity 5
    • FulfillmentDate は 2019 年 2 月 2 日、FulfillmentID は 52、OrderID は 1、OrderLine は 1、FulfillmentQuantity は 3 ですFulfillmentDate February 2 2019, FulfillmentID 52, OrderID 1, OrderLine 1, FulfillmentQuantity 3
    • FulfillmentDate は 2019 年 1 月 1 日、FulfillmentID は 53、OrderID は 1、OrderLine は 2、FulfillmentQuantity は 10 ですFulfillmentDate January 1 2019, FulfillmentID 53, OrderID 1, OrderLine 2, FulfillmentQuantity 10

モデルにクエリを実行するとどうなるかを見てみましょう。Let's see what happens when the model is queried. 次の表では、注文と調達の数量を Order テーブルの OrderID 列で比較しています。Here's a table visual comparing order and fulfillment quantities by the Order table OrderID column.

次の 3 つの列を含むテーブル ビジュアルを示す図。OrderID、OrderQuantity、および FulfillmentQuantity という 3 つの列があります。

ビジュアルには正確な結果が示されています。The visual presents an accurate result. しかし、モデルの有用性は限られています。フィルター処理またはグループ化できるのは、Order テーブルの OrderID 列でのみとなります。However, the usefulness of the model is limited—you can only filter or group by the Order table OrderID column.

多対多ファクトの関連付けに関するガイダンスRelate many-to-many facts guidance

一般には、多対多カーディナリティを使用して、2 つのファクトの種類のテーブルを直接関連付けることはお勧めしません。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. この例では、ビジュアルでフィルター処理またはグループ化できるのは、Order テーブルの OrderID 列でのみとなります。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. 詳細については、Power BI Desktop でのモデル リレーションシップ (リレーションシップの評価) に関する記事をご覧ください。For more information, see Model relationships in Power BI Desktop (Relationship evaluation).

ファクトの種類のテーブルを直接関連付けるのではなく、スター スキーマ設計原則を採用することをお勧めします。Instead of relating fact-type tables directly, we recommend you adopt Star Schema 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.

より優れたソリューションについて考えてみましょう。Let's consider a better solution.

モデルを示す図には、次の 6 つのテーブルが含まれます。OrderLine、OrderDate、Order、Fulfillment、Product、および FulfillmentDate。

次の設計変更に注目してください。Notice the following design changes:

  • モデルには現在、次の 4 つの追加テーブルがあります: OrderLineOrderDateProduct、および FulfillmentDateThe model now has four additional tables: OrderLine, OrderDate, Product, and FulfillmentDate
  • 4 つの追加テーブルはすべてディメンションの種類のテーブルであり、一対多リレーションシップではこれらのテーブルがファクトの種類のテーブルに関連付けられますThe four additional tables are all dimension-type tables, and one-to-many relationships relate these tables to the fact-type tables
  • OrderLine テーブルには、OrderLineID 列が含まれており、100 を乗算した OrderID 値と、OrderLine 値 (各注文明細行の一意識別子) を表しています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
  • OrderFulfillment テーブルには現在、OrderLineID 列が含まれており、OrderIDOrderLine 列は含まれなくなりましたThe Order and Fulfillment tables now contain an OrderLineID column, and they no longer contain the OrderID and OrderLine columns
  • Fulfillment テーブルには現在、OrderDateProductID 列が含まれていますThe Fulfillment table now contains OrderDate and ProductID columns
  • FulfillmentDate テーブルは、Fulfillment テーブルにのみ関連していますThe FulfillmentDate table relates only to the Fulfillment table
  • すべての一意識別子列は非表示になっていますAll unique identifier columns are hidden

時間をかけてスター スキーマの設計原則を適用することには、次のような利点があります。Taking the time to apply star schema design principles 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
  • OrderLineOrderDate、または Product テーブルに適用されたフィルターは、両方のファクトの種類のテーブルに伝達されます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. 詳細については、Power BI Desktop でのモデル リレーションシップ (リレーションシップの評価) に関する記事をご覧ください。For more information, see Model relationships in Power BI Desktop (Relationship evaluation).

より高い粒度のファクトを関連付けるRelate higher grain facts

この多対多シナリオは、この記事で既に説明した他の 2 つのシナリオとは大きく異なります。This many-to-many scenario is very different from the other two already described in this article.

次の 4 つのテーブルを含む例を考えてみましょう: DateSalesProduct、および TargetLet's consider an example involving four tables: Date, Sales, Product, and Target. DateProduct はディメンションの種類のテーブルであり、一対多リレーションシップでは、それぞれが Sales というファクトの種類のテーブルに関連付けられます。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. しかし、Target テーブルは、まだ他のテーブルに関連付けられていません。The Target table, however, is yet to be related to the other tables.

次の 4 つのテーブルを含むモデルを示す図: Date、Sales、Product、および Target。

Target テーブルには、次の 3 つの列が含まれています: CategoryTargetQuantity、および TargetYearThe 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.

Target テーブルに次の 3 つの列が含まれていることを示す図: TargetYear、Category、および TargetQuantity。

Target テーブルでは、ディメンションの種類のテーブルよりも高いレベルのデータが格納されるため、一対多リレーションシップを作成することはできません。Because the Target table stores data at a higher level than the dimension-type tables, a one-to-many relationship cannot be created. しかし、これはリレーションシップの 1 つにのみ当てはまることです。Well, it's true for just one of the relationships. ここでは、Target テーブルをディメンションの種類のテーブルにどのように関連付けられるかを説明します。Let's explore how the Target table can be related to the dimension-type tables.

より高い粒度の期間を関連付けるRelate higher grain time periods

DateTarget テーブルの間のリレーションシップは、一対多リレーションシップである必要があります。A relationship between the Date and Target tables should be a one-to-many relationship. これは、TargetYear 列の値が日付であるためです。It's because the TargetYear column values are dates. この例では、各 TargetYear 列の値は、ターゲット年の最初の日付です。In this example, each TargetYear column value is the first date of the target year.

ヒント

日よりも高い時間の粒度でファクトを格納する場合は、列のデータ型を Date (または、日付キーを使用する場合は整数) に設定します。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. たとえば、年期は年の 1 月 1 日として記録され、月期はその月の最初の日として記録されます。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. それ以外のすべての日 (1 月を除くすべての月) では、ターゲット数量が空白として集計されます。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. このビジュアルでは、TargetQuantity 列が集計されていますThe visual is summarizing the TargetQuantity column. (マトリックス行に対して [データのない項目を表示する] オプションが有効になっている)。(The Show items with no data option has been enabled for the matrix rows.)

マトリックス ビジュアルで、2020 年のターゲット数量が 270 として表示されていることを示す図。

この動作を回避するために、メジャーを使用して、ファクト データの集計を制御することをお勧めします。To avoid this behavior, we recommend you control the summarization of your fact data by using measures. 集計を制御する方法の 1 つは、下位レベルの期間に対してクエリが実行されたときに空白を返すことです。One way to control the summarization is to return BLANK when lower-level time periods are queried. いくつかの高度な DAX で定義されているもう 1 つの方法は、下位レベルの期間にわたって値を分配することです。Another way—defined with some sophisticated DAX—is to apportion values across lower-level time periods.

ISFILTERED DAX 関数を使用する次のメジャー定義について考えてみます。Consider the following measure definition that uses the ISFILTERED DAX function. DateMonth 列がフィルター処理されていない場合にのみ、値が返されます。It only returns a value when the Date or Month columns aren't filtered.

Target Quantity =
IF(
    NOT ISFILTERED('Date'[Date])
        && NOT ISFILTERED('Date'[Month]),
    SUM(Target[TargetQuantity])
)

これで、次のマトリックス ビジュアルで、Target Quantity メジャーが使用されるようになりました。The following matrix visual now uses the Target Quantity measure. これは、毎月のターゲット数量がすべて空白であることを示しています。It shows that all monthly target quantities are BLANK.

2020 年のターゲット数量が 270 で、毎月の値が空白であることが示されているマトリックス視覚エフェクトの図。

より高い粒度を関連付ける (日付以外)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).

Category 列 (ProductTarget テーブルの両方のもの) には、重複値が含まれています。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.

Target テーブルと Product テーブルのモデルを示す図。

次は、テーブル行を見てみましょう。Let's now take a look at the table rows.

2 つのテーブルを含むモデルを示す図: Target と Product。

Target テーブルには、4 つの行、つまり、ターゲット年 (2019 と 2020) ごとに 2 行と、2 つのカテゴリ (Clothing と Accessories) があります。In the Target table, there are four rows: two rows for each target year (2019 and 2020), and two categories (Clothing and Accessories). Product テーブルには、3 つの製品があります。In the Product table, there are three products. 2 つは衣料カテゴリに属し、1 つはアクセサリ カテゴリに属しています。Two belong to the clothing category, and one belongs to the accessories category. 衣料の色の 1 つは緑で、残りの 2 つは青です。One of the clothing colors is green, and the remaining two are blue.

Product テーブルの Category 列でグループ化するテーブル ビジュアルでは、次の結果が得られました。A table visual grouping by the Category column from the Product table produces the following result.

次の 2 つの列を持つテーブル ビジュアルを示す図: Category と TargetQuantity。

このビジュアルでは、正しい結果が得られました。This visual produces the correct result. 次は、Product テーブルの Color 列を使用して、ターゲット数量をグループ化するとどうなるかを考えてみましょう。Let's now consider what happens when the Color column from the Product table is used to group target quantity.

次の 2 つの列を持つテーブル ビジュアルを示す図: Color と TargetQuantity。

このビジュアルでは、データが誤った表示になっています。The visual produces a misrepresentation of the data. ここで何が起きているのでしょうか。What is happening here?

Product テーブルの Color 列にフィルターを適用すると、2 つの行が生成されます。A filter on the Color column from the Product table results in two rows. 行の 1 つは Clothing カテゴリ用で、もう 1 つは Accessories カテゴリ用です。One of the rows is for the Clothing category, and the other is for the Accessories category. これら 2 つのカテゴリ値は、フィルターとして Target テーブルに伝達されます。These two category values are propagated as filters to the Target table. つまり、青色は 2 つのカテゴリの製品で使用されるため、ターゲットのフィルター処理には "それらのカテゴリ" が使用されます。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.

次のメジャー定義について考えます。Consider the following measure definition. カテゴリ レベルの下にあるすべての Product テーブル列が、フィルターに対してテストされていることに注目してください。Notice that all Product table columns that are beneath the category level are tested for filters.

Target Quantity =
IF(
    NOT ISFILTERED('Product'[ProductID])
        && NOT ISFILTERED('Product'[Product])
        && NOT ISFILTERED('Product'[Color]),
    SUM(Target[TargetQuantity])
)

これで、次のテーブル ビジュアルで、Target Quantity メジャーが使用されるようになりました。The following table visual now uses the Target Quantity measure. これは、すべての色のターゲット数量が空白であることを示しています。It shows that all color target quantities are BLANK.

次の 2 つの列を持つテーブル ビジュアルを示す図: Color と TargetQuantity。

最終的なモデル設計は次のようになります。The final model design looks like the following.

Date および Target テーブルが一対多リレーションシップで関連付けられていることを示す図。

より高い粒度のファクトの関連付けに関するガイダンス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:

  • より高い粒度のファクトの日付の場合: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

次の手順Next steps

この記事に関する詳細については、次のリソースを参照してください。For more information related to this article, check out the following resources: