Richtlijnen voor veel-op-veel-relatiesMany-to-many relationship guidance

Dit artikel is geschreven voor iedereen die gegevensmodellen maakt met Power BI Desktop.This article targets you as a data modeler working with Power BI Desktop. Er worden drie verschillende veel-op-veel-modelleringsscenario's beschreven.It describes three different many-to-many modeling scenarios. Ook worden er richtlijnen gegeven voor hoe u voor deze scenario's kunt ontwerpen in uw modellen.It also provides you with guidance on how to successfully design for them in your models.

Notitie

Dit artikel bevat geen inleiding tot modelrelaties.An introduction to model relationships is not covered in this article. Als u niet volledig vertrouwd bent met relaties, de eigenschappen ervan of het configureren ervan, is het aan te raden eerst het artikel Modelrelaties in Power BI Desktop te lezen.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.

Het is ook belangrijk dat u enig begrip hebt van het ontwerpen van stervormige schema's.It's also important that you have an understanding of star schema design. Zie Meer informatie over stervormige schema's en het belang daarvan voor Power BI voor meer informatie.For more information, see Understand star schema and the importance for Power BI.

Er zijn drie veel-op-veel-scenario's.There are, in fact, three many-to-many scenarios. Deze kunnen zich voordoen als u het volgende moet doen:They can occur when you're required to:

Veel-op-veel-dimensies relaterenRelate many-to-many dimensions

Laten we het eerste veel-op-veel-scenariotype eens gaan bekijken op basis van een voorbeeld.Let's consider the first many-to-many scenario type with an example. In het klassieke scenario worden twee entiteiten gerelateerd: klanten van een bank en bankrekeningen.The classic scenario relates two entities: bank customers and bank accounts. Bedenk dat klanten meerdere rekeningen kunnen hebben en dat een rekening aan meerdere klanten kan toebehoren.Consider that customers can have multiple accounts, and accounts can have multiple customers. Wanneer een rekening aan meerdere klanten toebehoort, worden deze gewoonlijk gemeenschappelijke rekeninghouders genoemd.When an account has multiple customers, they're commonly called joint account holders.

Het modelleren van deze entiteiten is eenvoudig.Modeling these entities is straight forward. Rekeningen worden in één dimensietabel opgeslagen en klanten in een andere dimensietabel.One dimension-type table stores accounts, and another dimension-type table stores customers. Zoals kenmerkend is voor dimensietabellen bevat elke tabel een id-kolom.As is characteristic of dimension-type tables, there's an ID column in each table. Als u de relatie tussen de twee tabellen wilt modelleren, is er een derde tabel nodig.To model the relationship between the two tables, a third table is required. Deze tabel wordt gewoonlijk een overbruggingstabel genoemd.This table is commonly referred to as a bridging table. In dit voorbeeld dient de brugtabel om er één rij voor elke klant-rekeningkoppeling in op te slaan.In this example, it's purpose is to store one row for each customer-account association. Als deze tabel alleen id-kolommen bevat, wordt deze een feitloze feitentabel genoemd.Interestingly, when this table only contains ID columns, it's called a factless fact table.

Hier volgt een vereenvoudigd modeldiagram van de drie tabellen.Here's a simplistic model diagram of the three tables.

Diagram met een model met drie tabellen.

De eerste tabel heet Accounten bevat twee kolommen: AccountID en Account.The first table is named Account, and it contains two columns: AccountID and Account. De tweede tabel heet AccountCustomer en bevat twee kolommen: AccountID en CustomerID.The second table is named AccountCustomer, and it contains two columns: AccountID and CustomerID. De derde tabel heet Customer en bevat twee kolommen: CustomerID en Customer.The third table is named Customer, and it contains two columns: CustomerID and Customer. Er zijn geen relaties tussen de tabellen.Relationships don't exist between any of the tables.

Er worden een-op-veel-relaties toegevoegd om de tabellen te koppelen.Two one-to-many relationships are added to relate the tables. Hier volgt een bijgewerkt modeldiagram van de gerelateerde tabellen.Here's an updated model diagram of the related tables. De feitentabel Transaction is toegevoegd.A fact-type table named Transaction has been added. Hierin worden rekeningtransacties opgeslagen.It records account transactions. De overbruggingstabel en alle id-kolommen zijn verborgen.The bridging table and all ID columns have been hidden.

Diagram met het model dat nu de vier tabellen bevat.

Het modeldiagram is zodanig gewijzigd dat de tabelrijen worden weergegeven om aan te geven hoe de doorgifte van relatiefilters werkt.To help describe how the relationship filter propagation works, the model diagram has been modified to reveal the table rows.

Notitie

Het is niet mogelijk om tabelrijen weer te geven in het Power BI Desktop-modeldiagram.It's not possible to display table rows in the Power BI Desktop model diagram. Het wordt wel gedaan in dit artikel om duidelijke voorbeelden te kunnen geven.It's done in this article to support the discussion with clear examples.

Diagram met het model dat nu de tabelrijen bevat.

De rijgegevens voor de vier tabellen worden beschreven in de volgende lijst:The row details for the four tables are described in the following bulleted list:

  • De tabel Account (rekening) heeft twee rijen:The Account table has two rows:
    • AccountID 1 is voor Account-01AccountID 1 is for Account-01
    • AccountID 2 is voor Account-02AccountID 2 is for Account-02
  • De tabel Customer (klant) heeft twee rijen:The Customer table has two rows:
    • CustomerID 91 is voor Customer-91CustomerID 91 is for Customer-91
    • CustomerID 92 is voor Customer-92CustomerID 92 is for Customer-92
  • De tabel AccountCustomer heeft drie rijen:The AccountCustomer table has three rows:
    • AccountID 1 is gekoppeld aan CustomerID 91AccountID 1 is associated with CustomerID 91
    • AccountID 1 is gekoppeld aan CustomerID 92AccountID 1 is associated with CustomerID 92
    • AccountID 2 is gekoppeld aan CustomerID 92AccountID 2 is associated with CustomerID 92
  • De tabel Transaction (transactie) heeft drie rijen:The Transaction table has three rows:
    • Date (datum) 1 januari 2019, AccountID (rekening-id) 1, Amount (bedrag) 100Date January 1 2019, AccountID 1, Amount 100
    • Date 2 februari 2019, AccountID 2, Amount 200Date February 2 2019, AccountID 2, Amount 200
    • Date 3 maart 2019, AccountID 1, Amount -25Date March 3 2019, AccountID 1, Amount -25

Laten we eens kijken wat er gebeurt wanneer er een query op het model wordt uitgevoerd.Let's see what happens when the model is queried.

Hieronder staan twee visuals waarin de kolom Amount van de tabel Transaction wordt samengevat.Below are two visuals that summarize the Amount column from the Transaction table. De eerste visual is gegroepeerd op rekening zodat de som van de kolommen Amount het rekeningsaldo aangeeft.The first visual groups by account, and so the sum of the Amount columns represents the account balance. De tweede visual is gegroepeerd op klant zodat de som van de kolommen Amount het klantsaldo aangeeft.The second visual groups by customer, and so the sum of the Amount columns represents the customer balance.

Diagram met twee rapportvisualisaties die naast elkaar worden weergegeven.

De eerste visual heet Account Balance (rekeningsaldo) en bevat twee kolommen: Account en Amount.The first visual is titled Account Balance, and it has two columns: Account and Amount. Het volgende resultaat wordt erin weergegeven:It displays the following result:

  • Het saldo van Account-01 is 75Account-01 balance amount is 75
  • Het saldo van Account-02 is 200Account-02 balance amount is 200
  • Het totaal is 275The total is 275

De tweede visual heet Customer Balance (klantsaldo) en bevat twee kolommen: Customer en Amount.The second visual is titled Customer Balance, and it has two columns: Customer and Amount. Het volgende resultaat wordt erin weergegeven:It displays the following result:

  • Het saldo van Customer-91 is 275Customer-91 balance amount is 275
  • Het saldo van Customer-92 is 275Customer-92 balance amount is 275
  • Het totaal is 275The total is 275

Een korte blik op de tabelrijen en de visual Account Balance wijst uit dat de resultaten voor elke rekening en het totaalbedrag kloppen.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. Dat komt doordat elke groepering van rekeningen resulteert in filterdoorgifte naar de tabel Transaction voor die rekening.It's because each account grouping results in a filter propagation to the Transaction table for that account.

Er lijkt echter iets mis met de visual Customer Balance.However, something doesn't appear correct with the Customer Balance visual. Elke klant in de visual Customer Balance heeft hetzelfde saldo als het totaalsaldo.Each customer in the Customer Balance visual has the same balance as the total balance. Dit resultaat kan alleen kloppen als elke klant een gemeenschappelijke rekeninghouder van elke rekening is.This result could only be correct if every customer was a joint account holder of every account. Dat is in dit voorbeeld niet het geval.That's not the case in this example. Het probleem heeft te maken met filterdoorgifte.The issue is related to filter propagation. Die loopt niet helemaal door tot aan de tabel Transaction.It's not flowing all the way to the Transaction table.

Volg maar eens de richtingen van het relatiefilter van de tabel Customer naar de tabel Transaction.Follow the relationship filter directions from the Customer table to the Transaction table. Het moet duidelijk zijn dat de relatie tussen de tabel Account en de tabel AccountCustomer in de verkeerde richting wordt doorgegeven.It should be apparent that the relationship between the Account and AccountCustomer table is propagating in the wrong direction. De filterrichting voor deze relatie moet worden ingesteld op Beide.The filter direction for this relationship must be set to Both.

Diagram met het model dat is bijgewerkt.

Diagram met dezelfde twee rapportvisuals naast elkaar.

Zoals verwacht is er niets gewijzigd aan de visual Account Balance.As expected, there has been no change to the Account Balance visual.

De visual Customer Balance bevat nu echter het volgende resultaat:The Customer Balance visuals, however, now displays the following result:

  • Het saldo van Customer-91 is 75Customer-91 balance amount is 75
  • Het saldo van Customer-92 is 275Customer-92 balance amount is 275
  • Het totaal is 275The total is 275

De visual Customer Balance bevat nu het juiste resultaat.The Customer Balance visual now displays a correct result. Volg de filterrichtingen voor uzelf en zie hoe de klantsaldi zijn berekend.Follow the filter directions for yourself, and see how the customer balances were calculated. Begrijp ook dat het visualtotaal alle klanten betekent.Also, understand that the visual total means all customers.

Iemand die niet bekend is met de modelrelaties zou kunnen concluderen dat het resultaat onjuist is.Someone unfamiliar with the model relationships could conclude that the result is incorrect. Diegene kan vragen: Waarom is het totaal voor Customer-91 en Customer-92 niet gelijk aan 350 (75 + 275)?They might ask: Why isn't the total balance for Customer-91 and Customer-92 equal to 350 (75 + 275)?

Voor het antwoord op deze vraag is kennis van de veel-op-veel-relatie nodig.The answer to their question lies in understanding the many-to-many relationship. Elk klantsaldo kan de toevoeging van meerdere rekeningsaldi vertegenwoordigen, waardoor de klantsaldi niet-additief zijn.Each customer balance can represent the addition of multiple account balances, and so the customer balances are non-additive.

Richtlijnen voor het relateren van veel-op-veel-dimensiesRelate many-to-many dimensions guidance

Voor veel-op-veel-relaties tussen dimensietabellen gelden de volgende richtlijnen:When you have a many-to-many relationship between dimension-type tables, we provide the following guidance:

  • Voeg elke veel-op-veel-gerelateerde entiteit toe als een modeltabel, zodat deze een unieke id-kolom heeftAdd each many-to-many related entity as a model table, ensuring it has a unique identifier (ID) column
  • Voeg een overbruggingstabel toe om gekoppelde entiteiten in op te slaanAdd a bridging table to store associated entities
  • Maak een-op-veel-relaties tussen de drie tabellenCreate one-to-many relationships between the three tables
  • Configureer één bidirectionele relatie zodat de filterdoorgifte helemaal doorloopt naar de feitentabellenConfigure one bi-directional relationship to allow filter propagation to continue to the fact-type tables
  • Stel de eigenschap Null-waarde toegestaan van id-kolommen in op FALSE als u geen ontbrekende id-waarden wilt. Anders mislukt het vernieuwen van gegevens als er waarden ontbrekenWhen 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
  • Verberg de overbruggingstabel (tenzij deze aanvullende kolommen of metingen bevat die nodig zijn voor rapportage)Hide the bridging table (unless it contains additional columns or measures required for reporting)
  • Verberg alle id-kolommen die niet geschikt zijn voor rapportage (bijvoorbeeld wanneer id's surrogaatsleutels zijn)Hide any ID columns that aren't suitable for reporting (for example, when IDs are surrogate keys)
  • Als het zinvol is om een id-kolom zichtbaar te laten, zorg er dan voor dat deze zich aan de 'een'-zijde van de relatie bevindt. Verberg altijd de kolom aan de 'veel'-zijde.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. Dit geeft de beste filterprestaties.It results in the best filter performance.
  • Geef uitleg aan uw rapportgebruikers om verwarring of misinterpretatie te voorkomen. U kunt beschrijvingen met tekstvakken of knopinfo voor visuele koptekst toevoegenTo avoid confusion or misinterpretation, communicate explanations to your report users—you can add descriptions with text boxes or visual header tooltips

Het is niet raadzaam om veel-op-veel-dimensietabellen rechtstreeks te relateren.We don't recommend you relate many-to-many dimension-type tables directly. Voor deze ontwerpbenadering moet u een relatie met een veel-op-veel-kardinaliteit configureren.This design approach requires configuring a relationship with a many-to-many cardinality. Dit is te realiseren, maar dat impliceert wel dat de gerelateerde kolommen dubbele waarden krijgen.Conceptually it can be achieved, yet it implies that the related columns will contain duplicate values. Het is echter een gangbare ontwerppraktijk om dimensietabellen een id-kolom te geven.It's a well-accepted design practice, however, that dimension-type tables have an ID column. Zorg ervoor dat dimensietabellen de id-kolom gebruiken als de 'een'-zijde van een relatie.Dimension-type tables should always use the ID column as the "one" side of a relationship.

Veel-op-veel-feiten relaterenRelate many-to-many facts

Het tweede veel-op-veel-scenario heeft betrekking op het relateren van twee feitentabellen.The second many-to-many scenario type involves relating two fact-type tables. Twee feitentabellen kunnen rechtstreeks worden gerelateerd.Two fact-type tables can be related directly. Deze ontwerptechniek kan handig zijn om snel en eenvoudig gegevens te verkennen.This design technique can be useful for quick and simple data exploration. Deze ontwerpbenadering is over het algemeen echter niet aan te raden.However, and to be clear, we generally don't recommend this design approach. Verderop in deze sectie wordt uitgelegd waarom.We'll explain why later in this section.

Laten we eens kijken naar een voorbeeld met twee feitentabellen: Order (order) en Fulfillment (levering).Let's consider an example that involves two fact-type tables: Order and Fulfillment. De tabel Order bevat één rij per orderregel en de tabel Fulfillment kan nul of meer rijen per orderregel bevatten.The Order table contains one row per order line, and the Fulfillment table can contains zero or more rows per order line. Rijen in de tabel Order vertegenwoordigen verkooporders.Rows in the Order table represent sales orders. Rijen in de tabel Fulfillment vertegenwoordigen orderitems die zijn verzonden.Rows in the Fulfillment table represent order items that have been shipped. Een veel-op-veel-relatie heeft betrekking op de twee OrderID-kolommen, met alleen filterdoorgifte vanuit de tabel Order (filtering van Order naar Fulfillment).A many-to-many relationship relates the two OrderID columns, with filter propagation only from the Order table (Order filters Fulfillment).

Diagram met een model met twee tabellen: Order en Fulfillment.

De relatiekardinaliteit is ingesteld op veel-op-veel om ondersteuning te bieden voor het opslaan van dubbele OrderID-waarden in beide tabellen.The relationship cardinality is set to many-to-many to support storing duplicate OrderID values in both tables. In de tabel Order kunnen dubbele OrderID-waarden aanwezig zijn omdat een order meerdere regels kan hebben.In the Order table, duplicate OrderID values can exist because an order can have multiple lines. In de tabel Fulfillment kunnen dubbele OrderID-waarden aanwezig zijn omdat orders meerdere regels kunnen hebben en orderregels kunnen worden geleverd via meerdere zendingen.In the Fulfillment table, duplicate OrderID values can exist because orders may have multiple lines, and order lines can be fulfilled by many shipments.

Nu gaan we de tabelrijen bekijken.Let's now take a look at the table rows. In de tabel Fulfillment ziet u dat orderregels kunnen worden geleverd via meerdere zendingen.In the Fulfillment table, notice that order lines can be fulfilled by multiple shipments. (Het ontbreken van een orderregel betekent dat de order nog moet worden geleverd.)(The absence of an order line means the order is yet to be fulfilled.)

Diagram met het model dat nu de tabelrijen bevat.

De rijgegevens voor de twee tabellen worden beschreven in de volgende lijst:The row details for the two tables are described in the following bulleted list:

  • De tabel Order heeft vijf rijen:The Order table has five rows:
    • OrderDate (orderdatum) 1 januari 2019, OrderID (order-id) 1, OrderLine (orderregel) 1, ProductID (product-id) Prod-A, OrderQuantity (orderaantal) 5, Sales (verkoop) 50OrderDate January 1 2019, OrderID 1, OrderLine 1, ProductID Prod-A, OrderQuantity 5, Sales 50
    • OrderDate 1 januari 2019, OrderID 1, OrderLine 2, ProductID Prod-B, OrderQuantity 10, Sales 80OrderDate January 1 2019, OrderID 1, OrderLine 2, ProductID Prod-B, OrderQuantity 10, Sales 80
    • OrderDate 2 februari 2019, OrderID 2, OrderLine 1, ProductID Prod-B, OrderQuantity 5, Sales 40OrderDate February 2 2019, OrderID 2, OrderLine 1, ProductID Prod-B, OrderQuantity 5, Sales 40
    • OrderDate 2 februari 2019, OrderID 2, OrderLine 2, ProductID Prod-C, OrderQuantity 1, Sales 20OrderDate February 2 2019, OrderID 2, OrderLine 2, ProductID Prod-C, OrderQuantity 1, Sales 20
    • OrderDate 3 maart 2019, OrderID 3, OrderLine 1, ProductID Prod-C, OrderQuantity 5, Sales 100OrderDate March 3 2019, OrderID 3, OrderLine 1, ProductID Prod-C, OrderQuantity 5, Sales 100
  • De tabel Fulfillment heeft vier rijen:The Fulfillment table has four rows:
    • FulfillmentDate (leverdatum) 1 januari 2019, FulfillmentID (lever-id) 50, OrderID (order-id) 1, OrderLine (orderregel) 1, FulfillmentQuantity (leveringsaantal) 2FulfillmentDate January 1 2019, FulfillmentID 50, OrderID 1, OrderLine 1, FulfillmentQuantity 2
    • FulfillmentDate 2 februari 2019, FulfillmentID 51, OrderID 2, OrderLine 1, FulfillmentQuantity 5FulfillmentDate February 2 2019, FulfillmentID 51, OrderID 2, OrderLine 1, FulfillmentQuantity 5
    • FulfillmentDate 2 februari 2019, FulfillmentID 52, OrderID 1, OrderLine 1, FulfillmentQuantity 3FulfillmentDate February 2 2019, FulfillmentID 52, OrderID 1, OrderLine 1, FulfillmentQuantity 3
    • FulfillmentDate 1 januari 2019, FulfillmentID 53, OrderID 1, OrderLine 2, FulfillmentQuantity 10FulfillmentDate January 1 2019, FulfillmentID 53, OrderID 1, OrderLine 2, FulfillmentQuantity 10

Laten we eens kijken wat er gebeurt wanneer er een query op het model wordt uitgevoerd.Let's see what happens when the model is queried. Hier volgt een tabelvisual waarin de order- en leveringsaantallen worden vergelijken via de kolom OrderID van de tabel Order.Here's a table visual comparing order and fulfillment quantities by the Order table OrderID column.

Diagram met een tabelvisual met drie kolommen: OrderID, OrderQuantity en FulfillmentQuantity.

Het resultaat in de visual klopt.The visual presents an accurate result. Het nut van het model is echter beperkt: u kunt alleen filteren of groeperen op de kolom OrderID van de tabel Order.However, the usefulness of the model is limited—you can only filter or group by the Order table OrderID column.

Richtlijnen voor het relateren van veel-op-veel-feitenRelate many-to-many facts guidance

Over het algemeen is het niet aan te raden om twee feitentabellen rechtstreeks te relateren via veel-op-veel-kardinaliteit.Generally, we don't recommend relating two fact-type tables directly using many-to-many cardinality. De belangrijkste reden hiervoor is dat het model geen flexibiliteit biedt in de manieren waarop u het rapport kunt filteren of groeperen.The main reason is because the model won't provide flexibility in the ways you report visuals filter or group. In het voorbeeld is het alleen mogelijk om visuals te filteren of te groeperen op de kolom OrderID van de tabel Order.In the example, it's only possible for visuals to filter or group by the Order table OrderID column. Een andere reden heeft betrekking op de kwaliteit van uw gegevens.An additional reason relates to the quality of your data. Als er integriteitsproblemen zijn met uw gegevens, worden er tijdens het uitvoeren van query's mogelijk rijen weggelaten door de aard van de zwakke relatie.If your data has integrity issues, it's possible some rows may be omitted during querying due to the nature of the weak relationship. Raadpleeg Modelrelaties in Power BI Desktop (evaluatie van relaties) voor meer informatie.For more information, see Model relationships in Power BI Desktop (Relationship evaluation).

In plaats van feitentabellen te relateren, is het raadzaam om de ontwerpprincipes van stervormige schema's te volgen.Instead of relating fact-type tables directly, we recommend you adopt Star Schema design principles. Dit doet u door dimensietabellen toe te voegen.You do it by adding dimension-type tables. De dimensietabellen zijn dan via een-op-veel-relaties gerelateerd aan de feitentabellen.The dimension-type tables then relate to the fact-type tables by using one-to-many relationships. Deze ontwerpbenadering is robuust vanwege de flexibele rapportageopties.This design approach is robust as it delivers flexible reporting options. U kunt filteren of groeperen met behulp van een van de dimensiekolommen en u kunt elke gerelateerde feitentabel samenvatten.It lets you filter or group using any of the dimension-type columns, and summarize any related fact-type table.

Laten we eens kijken naar een betere oplossing.Let's consider a better solution.

Diagram met een model met zes tabellen: OrderLine, OrderDate, Order, Fulfillment, Product en FulfillmentDate.

Let op de volgende ontwerpwijzigingen:Notice the following design changes:

  • Het model bevat nu vier extra tabellen: OrderLine, OrderDate, Product en FulfillmentDateThe model now has four additional tables: OrderLine, OrderDate, Product, and FulfillmentDate
  • De vier extra tabellen zijn allemaal dimensietabellen, en met een-op-veel-relaties worden deze tabellen gekoppeld aan de feitentabellenThe four additional tables are all dimension-type tables, and one-to-many relationships relate these tables to the fact-type tables
  • De tabel OrderLine bevat de kolom OrderLineID met daarin de waarde van OrderID vermenigvuldigd met 100, plus de waarde OrderLine, een unieke id voor elke orderregelThe 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
  • De tabellen Order en Fulfillment bevatten nu een kolom OrderLineID en bevatten niet meer de kolommen OrderID en OrderLineThe Order and Fulfillment tables now contain an OrderLineID column, and they no longer contain the OrderID and OrderLine columns
  • De tabel Fulfillment bevat nu de kolommen OrderDate en ProductIDThe Fulfillment table now contains OrderDate and ProductID columns
  • De tabel FulfillmentDate heeft alleen een relatie met de tabel FulfillmentThe FulfillmentDate table relates only to the Fulfillment table
  • Alle kolommen met unieke id's zijn verborgenAll unique identifier columns are hidden

Het toepassen van de ontwerpprincipes van het stervormige schema biedt de volgende voordelen:Taking the time to apply star schema design principles delivers the following benefits:

  • Uw rapportvisuals zijn te filteren of te groeperen op elke zichtbare kolom van de dimensietabellenYour report visuals can filter or group by any visible column from the dimension-type tables
  • In uw rapportvisuals zijn alle zichtbare kolommen van de feitentabellen samen te vattenYour report visuals can summarize any visible column from the fact-type tables
  • Filters die worden toegepast op de tabellen OrderLine, OrderDate of Product worden doorgegeven aan beide feitentabellenFilters applied to the OrderLine, OrderDate, or Product tables will propagate to both fact-type tables
  • Alle relaties zijn een-op-veel en elke relatie is een sterke relatie.All relationships are one-to-many, and each relationship is a strong relationship. Problemen met gegevensintegriteit worden niet gemaskeerd.Data integrity issues won't be masked. Raadpleeg Modelrelaties in Power BI Desktop (evaluatie van relaties) voor meer informatie.For more information, see Model relationships in Power BI Desktop (Relationship evaluation).

Nauwkeurigere feiten relaterenRelate higher grain facts

Dit veel-op-veel-scenario is heel anders dan de twee die al eerder in dit artikel zijn beschreven.This many-to-many scenario is very different from the other two already described in this article.

Laten we eens kijken naar een voorbeeld met vier tabellen: Date (datum), Sales (verkoop), Product (product) en Target (doel).Let's consider an example involving four tables: Date, Sales, Product, and Target. Date en Product zijn dimensietabellen en hebben een-op-veel-relaties met de feitentabel Sales.The Date and Product are dimension-type tables, and one-to-many relationships relate each to the Sales fact-type table. Tot nu toe is het een goed ontwerp voor een stervormig schema.So far, it represents a good star schema design. De tabel Target moet echter nog worden gerelateerd aan de andere tabellen.The Target table, however, is yet to be related to the other tables.

Diagram met een model met vier tabellen: Date, Sales, Product en Target.

De tabel Target bevat drie kolommen: Category (categorie), TargetQuantity (doelaantal) en TargetYear (doeljaar).The Target table contains three columns: Category, TargetQuantity, and TargetYear. De tabelrijen geven een granulariteit aan op jaar en productcategorie.The table rows reveal a granularity of year and product category. Met andere woorden: doelen, waarmee de verkoopprestaties worden gemeten, worden elk jaar ingesteld voor elke productcategorie.In other words, targets—used to measure sales performance—are set each year for each product category.

Diagram met de Doeltabel met drie kolommen: TargetYear, Category en TargetQuantity.

Omdat in de tabel Target gegevens op een hoger niveau worden opgeslagen dan in de dimensietabellen, kan er geen een-op-veel-relatie worden gemaakt.Because the Target table stores data at a higher level than the dimension-type tables, a one-to-many relationship cannot be created. Dat geldt althans voor een van de relaties.Well, it's true for just one of the relationships. Laten we eens kijken hoe de tabel Target kan worden gerelateerd aan de dimensietabellen.Let's explore how the Target table can be related to the dimension-type tables.

Nauwkeurigere perioden relaterenRelate higher grain time periods

Een relatie tussen de tabellen Date en Target moet een een-op-veel-relatie zijn.A relationship between the Date and Target tables should be a one-to-many relationship. De reden hiervoor is dat de waarden van de kolom TargetYear datums zijn.It's because the TargetYear column values are dates. In dit voorbeeld is elke waarde van de kolom TargetYear de eerste datum van het doeljaar.In this example, each TargetYear column value is the first date of the target year.

Tip

Bij het opslaan van feiten met een hogere tijdgranulatie dan dag, stelt u het kolomgegevenstype in op Datum (of Geheel getal als u datumsleutels gebruikt).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 de kolom slaat u een waarde op die de eerste dag van de tijdsperiode representeert.In the column, store a value representing the first day of the time period. Een jaarperiode wordt bijvoorbeeld vastgelegd als 1 januari van dat jaar en een maandperiode als de eerste dag van die maand.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.

Zorg er echter voor dat de filters op maand- of datumniveau een zinvol resultaat opleveren.Care must be taken, however, to ensure that month or date level filters produce a meaningful result. Zonder speciale berekeningslogica kan in visuals worden gerapporteerd dat de doeldatums letterlijk de eerste dag van elk jaar zijn.Without any special calculation logic, report visuals may report that target dates are literally the first day of each year. Alle andere dagen, plus alle maanden behalve januari, krijgen een leeg samengevat doelaantal.All other days—and all months except January—will summarize the target quantity as BLANK.

In de volgende matrixvisual ziet u wat er gebeurt wanneer de rapportgebruiker de details van de maanden van een jaar weergeeft.The following matrix visual shows what happens when the report user drills from a year into its months. In de visual wordt de kolom TargetQuantity samengevat.The visual is summarizing the TargetQuantity column. (De optie Items zonder gegevens weergeven is ingeschakeld voor de matrixrijen.)(The Show items with no data option has been enabled for the matrix rows.)

Diagram met een matrixvisual waarin het doelaantal van het jaar 2020 wordt weergegeven als 270.

We raden u aan het samenvatten van uw feitgegevens te beheren met metingen om dit gedrag te voorkomen.To avoid this behavior, we recommend you control the summarization of your fact data by using measures. Een van de manieren om de samenvatting te beheren, is BLANK (leeg) te retourneren als er een query wordt uitgevoerd op tijdsperioden van een lager niveau.One way to control the summarization is to return BLANK when lower-level time periods are queried. Een andere manier, gedefinieerd met enige geavanceerde DAX, is het verdelen van waarden over perioden van een lager niveau.Another way—defined with some sophisticated DAX—is to apportion values across lower-level time periods.

Overweeg de volgende metingsdefinitie met de DAX-functie ISFILTERED.Consider the following measure definition that uses the ISFILTERED DAX function. Er wordt alleen een waarde geretourneerd wanneer de kolommen Date of Month niet worden gefilterd.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])
)

In de volgende matrixvisual is nu gebruikgemaakt van de meting Target Quantity.The following matrix visual now uses the Target Quantity measure. U ziet dat alle maandelijkse doelaantallen leeg zijn.It shows that all monthly target quantities are BLANK.

Diagram met een matrixvisual waarin het doelaantal van het jaar 2020 wordt weergegeven als 270.

Nauwkeuriger relateren (geen datums)Relate higher grain (non-date)

Er is een andere ontwerpbenadering nodig bij het relateren van een niet-datumkolom van een dimensietabel met die van een feitentabel (die ook nauwkeuriger is dan de dimensietabel).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).

De kolommen Category (van zowel de tabel Product als Target) bevatten dubbele waarden.The Category columns (from both the Product and Target tables) contains duplicate values. Er is dus geen 'een' voor een een-op-veel-relatie.So, there's no "one" for a one-to-many relationship. In dit geval moet u een veel-op-veel-relatie maken.In this case, you'll need to create a many-to-many relationship. Bij deze relatie moeten filters in één richting worden doorgeven, van de dimensietabel naar de feitentabel.The relationship should propagate filters in a single direction, from the dimension-type table to the fact-type table.

Diagram met een model van de tabellen Doel en Product.

Nu gaan we de tabelrijen bekijken.Let's now take a look at the table rows.

Diagram met een model met twee tabellen: Target en Product.

In de tabel Target bevinden zich vier rijen: twee rijen voor elk doeljaar (2019 en 2020) en twee categorieën (Clothing (kleding) en Accessories (accessoires)).In the Target table, there are four rows: two rows for each target year (2019 and 2020), and two categories (Clothing and Accessories). Er zijn drie producten in de tabel Product.In the Product table, there are three products. Twee behoren er tot de categorie kleding en een hoort er bij de categorie accessoires.Two belong to the clothing category, and one belongs to the accessories category. Een van de kledingkleuren is groen en de resterende twee zijn blauw.One of the clothing colors is green, and the remaining two are blue.

Het groeperen van een tabelvisual op de kolom Category van de tabel Product geeft het volgende resultaat.A table visual grouping by the Category column from the Product table produces the following result.

Diagram met een tabelvisual met twee kolommen: Category en TargetQuantity.

Het resultaat in deze visual klopt.This visual produces the correct result. Laten we nu gaan kijken wat er gebeurt wanneer de kolom Color (kleur) van de tabel Product wordt gebruikt om het doelaantal te groeperen.Let's now consider what happens when the Color column from the Product table is used to group target quantity.

Diagram met een tabelvisual met twee kolommen: Color en TargetQuantity.

In deze visual zijn de gegevens verkeerd weergegeven.The visual produces a misrepresentation of the data. Wat is hier gebeurd?What is happening here?

Een filter op de kolom Color van de tabel Product levert twee rijen op.A filter on the Color column from the Product table results in two rows. Een van de rijen is voor de categorie Clothing en de andere is voor de categorie Accessories.One of the rows is for the Clothing category, and the other is for the Accessories category. Deze twee categoriewaarden worden doorgegeven als filters voor de tabel Target.These two category values are propagated as filters to the Target table. Met andere woorden, omdat de kleur blauw wordt gebruikt door producten uit twee categorieën, worden die categorieën gebruikt om de doelen te filteren.In other words, because the color blue is used by products from two categories, those categories are used to filter the targets.

Zoals eerder beschreven, is het raadzaam het samenvatten van uw feitgegevens te beheren met metingen om dit gedrag te voorkomen.To avoid this behavior, as described earlier, we recommend you control the summarization of your fact data by using measures.

Denk eens na over de volgende metingsdefinitie.Consider the following measure definition. Zoals u ziet, worden alle kolommen van de tabel Product die zich onder het categorieniveau bevinden getest op filters.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])
)

In de volgende tabelvisual is nu gebruikgemaakt van de meting Target Quantity.The following table visual now uses the Target Quantity measure. U ziet dat alle kleurdoelaantallen leeg zijn.It shows that all color target quantities are BLANK.

Diagram met een tabelvisual met twee kolommen: Color en TargetQuantity.

Het uiteindelijke modelontwerp ziet er als volgt uit.The final model design looks like the following.

Diagram met een model met de tabellen Datum en Doel die zijn gerelateerd via aan een een-op-veel-relatie.

Richtlijnen voor het relateren van nauwkeurigere feitenRelate higher grain facts guidance

Hier volgen richtlijnen voor het koppelen van een dimensietabel aan een feitentabel als in de feitentabel nauwkeurigere rijen worden opgeslagen dan in de dimensietabel: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:

  • Voor nauwkeurigere datums:For higher grain fact dates:
    • Sla de eerste datum van de periode op in de feitentabelIn the fact-type table, store the first date of the time period
    • Maak een een-op-veel-relatie tussen de datumtabel en de feitentabelCreate a one-to-many relationship between the date table and the fact-type table
  • Voor andere nauwkeurigere feiten:For other higher grain facts:
    • Maak een veel-op-veel-relatie tussen de dimensietabel en de feitentabelCreate a many-to-many relationship between the dimension-type table and the fact-type table
  • Voor beide typen:For both types:
    • Beheer het samenvatten met metingslogica: retourneer BLANK als er dimensiekolommen van een lager niveau worden gebruikt om te filteren of te groeperenControl summarization with measure logic—return BLANK when lower-level dimension-type columns are used to filter or group
    • Verberg samen te vatten kolommen van feitentabellen, zodat er alleen metingen kunnen worden gebruikt om de feitentabel samen te vattenHide summarizable fact-type table columns—this way, only measures can be used to summarize the fact-type table

Volgende stappenNext steps

Bekijk de volgende resources voor meer informatie over dit artikel:For more information related to this article, check out the following resources: