Vejledning til mange til mange-relationer
Denne artikel henvender sig til dig som dataudformer, der arbejder med Power BI Desktop. Den beskriver tre forskellige mange til mange-modelleringsscenarier. Den indeholder også en vejledning i, hvordan du kan designe dem korrekt i dine modeller.
Seddel
En introduktion til modelrelationer er ikke beskrevet i denne artikel. Hvis du ikke er helt fortrolig med relationer, deres egenskaber, eller hvordan du konfigurerer dem, anbefaler vi, at du først læser artiklen Modelrelationer i Power BI Desktop artikel.
Det er også vigtigt, at du har en forståelse af stjerneskemadesign. Du kan få flere oplysninger under Forstå stjerneskemaet og vigtigheden af Power BI.
Der er tre forskellige mange til mange-scenarier. De kan forekomme, når du skal:
- Relater to dimensionstabeller
- Relater to faktatabeller
- Relater faktatabeller med højere detaljering, når den faktatabel gemmer rækker med en højere detaljeringsværdi end rækkerne i dimensionstabellen
Relater mange til mange-dimensioner
Det klassiske mange til mange-scenarie relaterer to enheder, f.eks. bankkunder og bankkonti. Overvej, at kunder kan have flere konti, og konti kan have flere kunder. Når en konto har flere kunder, kaldes de ofte indehavere af en fælles konto.
Modellering af disse enheder er ligetil. En dimensionstabel gemmer konti, og en anden dimensionstabel gemmer kunder. Som det er karakteristisk for dimensionstabeller, er der en entydig identifikatorkolonne (ID) i hver tabel. Hvis du vil udforme relationen mellem de to tabeller, kræves der en tredje tabel. Denne tabel kaldes ofte en brotabel. I dette eksempel er det formålet at gemme én række for hver kundekontotilknytning. Det er interessant, at når denne tabel kun indeholder id-kolonner, kaldes den en faktaløs faktatabel.
Her er et forenklet diagram over de tre modeltabeller.
Den første tabel kaldes Account
og indeholder to kolonner: AccountID
og Account
. Den anden tabel kaldes AccountCustomer
og indeholder to kolonner: AccountID
og CustomerID
. Den tredje tabel hedder Customer
og indeholder to kolonner: CustomerID
og Customer
. Der findes ikke relationer mellem nogen af tabellerne.
Der tilføjes to en til mange-relationer for at relatere tabellerne. Her er et opdateret modeldiagram over de relaterede tabeller. Der er tilføjet en faktatabel med navnet Transaction
. Den registrerer kontotransaktioner. Brotabellen og alle identifikatorkolonner er blevet skjult.
Modeldiagrammet er blevet ændret for at hjælpe med at beskrive, hvordan overførsel af relationsfiltre fungerer, for at vise tabelrækkerne.
Rækkedetaljerne for de fire tabeller vises på følgende punktopstilling:
- Tabellen
Account
indeholder to rækker:-
AccountID
1 er til Account-01 -
AccountID
2 er til Account-02
-
- Tabellen
Customer
indeholder to rækker:-
CustomerID
91 er til Customer-91 -
CustomerID
92 er til Customer-92
-
- Tabellen
AccountCustomer
indeholder tre rækker:-
AccountID
1 er knyttet tilCustomerID
91 -
AccountID
1 er knyttet tilCustomerID
92 -
AccountID
2 er knyttet tilCustomerID
92
-
- Tabellen
Transaction
indeholder tre rækker:-
Date
. januar 2019AccountID
1Amount
100 -
Date
. februar 2019AccountID
2Amount
200 -
Date
. marts 2019AccountID
1Amount
-25
-
Lad os se, hvad der sker, når der sendes en forespørgsel til modellen.
På følgende billede er der to tabelvisualiseringer, der opsummerer den Amount
kolonne i tabellen Transaction
. Den første visualisering grupperes efter konto, så summen af de Amount
kolonner repræsenterer den kontosaldo. Den anden visualisering grupperes efter kunde, så summen af kolonnerne Amount
repræsenterer kundesaldo.
Den første tabelvisualisering (Kontosaldo) indeholder to kolonner: Account
og Amount
. Det viser følgende resultat:
- Konto-01 saldobeløbet er 75.
- Konto-02 saldobeløbet er 200.
- Totalen er 275.
Den anden tabelvisualisering (Kundesaldo) indeholder to kolonner: Customer
og Amount
. Det viser følgende resultat:
- Debitor-91 saldobeløbet er 275.
- Kunde-92 saldobeløbet er 275.
- Totalen er 275.
Et hurtigt blik på tabelrækkerne og visualiseringen Kontosaldo viser, at resultatet er korrekt for hver konto og det samlede beløb. Det skyldes, at hver kontogruppe resulterer i en filteroverførsel til den Transaction
tabel for den pågældende konto.
Noget ser dog ikke korrekt ud med visualiseringen Kundesaldo. Hver kunde i denne visualisering har den samme saldo som den samlede saldo. Dette resultat kunne kun være korrekt, hvis hver kunde var en fælles kontohaver for hver konto. Det er ikke tilfældet i dette eksempel. Der er et problem, og det er relateret til filteroverførsel. Filtre flyder ikke helt til tabellen Transaction
.
Hvis du følger filterretningerne for relationen fra tabellen Customer
til den Transaction
tabel, kan du bestemme, at relationen mellem tabellerne Account
og AccountCustomer
overføres i den forkerte retning. Filterretningen for denne relation skal angives til Both
.
Som forventet er der ikke foretaget nogen ændring af visualiseringen Kontosaldo.
Visualiseringen Kundesaldo viser dog nu følgende resultat:
- Kunde-91 saldobeløbet er 75.
- Kunde-92 saldobeløbet er 275.
- Totalen er 275.
Visualiseringen Kundesaldo viser nu et korrekt resultat. Følg selv filterretningerne, og se, hvordan kundesaldiene blev beregnet. Forstå også, at totalen for visualiseringen betyder, alle kunder.
En person, der ikke er fortrolig med modelrelationerne, kan konkludere, at resultatet er forkert. De spørger måske: Hvorfor er den samlede saldo for Customer-91
og Customer-92
ikke lig med 350 (75 + 275)?
Svaret på deres spørgsmål ligger i at forstå mange til mange-relationen. Hver kundesaldo kan repræsentere tilføjelsen af flere kontosaldi, så kundesaldiene ikke-additive.
Vejledning til relater mange til mange-dimensioner
Når du har en mange til mange-relation mellem dimensionstabeller, skal du følge denne vejledning:
- Tilføj hvert mange til mange-relateret objekt som en modeltabel for at sikre, at den har en id-kolonne.
- Tilføj en mellemtabel for at gemme tilknyttede objekter.
- Opret en til mange-relationer mellem de tre tabeller.
- Angiv én tovejsrelation for at tillade filteroverførsel at fortsætte til faktatabellen.
- Når det ikke er hensigtsmæssigt at have manglende id-værdier, skal du deaktivere egenskaben
Is Nullable
– dataopdateringen mislykkes, når der hentes manglende værdier. - Skjul brotabellen (medmindre den indeholder andre kolonner eller målinger, der kræves til rapportering).
- Skjul alle id-kolonner, der ikke er egnede til rapportering (f.eks. når kolonnerne gemmer surrogatnøgleværdier).
- Hvis det giver mening at lade en id-kolonne være synlig, skal du sørge for, at den er på "en"-siden af relationen – skjul altid kolonnen "mange". Det skyldes, at filtre, der anvendes på sliden "en", resulterer i en bedre filterydeevne.
- Hvis du vil undgå forvirring eller fejlfortolkning, skal du kommunikere forklaringer til dine rapportbrugere. Du kan tilføje beskrivelser med tekstfelter eller værktøjstip til overskriften for visualiseringer.
Vi anbefaler ikke, at du relaterer mange til mange-dimensionstabeller direkte. Denne designtilgang kræver, at du konfigurerer en relation med en mange til mange-kardinalitet. Det kan opnås konceptuelt, men det betyder, at de relaterede kolonner kan indeholde dubletværdier. Det er dog en vel accepteret designpraksis, at dimensionstabeller har en id-kolonne. Dimensionstabeller skal altid bruge kolonnen ID som "en"-siden af en relation.
Relater mange til mange-fakta
En anden mange til mange-scenarietype omfatter relatering af to faktatabeller. To faktatabeller kan relaterer direkte. Denne designteknik kan være nyttig til hurtig og enkel dataudforskning. Vi anbefaler dog generelt ikke denne designtilgang. Vi forklarer, hvorfor senere i dette afsnit.
Lad os se på et eksempel, der omfatter to faktatabeller: Order
og Fulfillment
. Tabellen Order
indeholder én række pr. ordrelinje, og den Fulfillment
tabel kan indeholde nul eller flere rækker pr. ordrelinje. Rækker i tabellen Order
repræsenterer salgsordrer. Rækker i tabellen Fulfillment
repræsenterer ordreelementer, der er leveret. En mange til mange-relation relaterer de OrderID
kolonner i hver tabel med filteroverførsel kun fra tabellen Order
(hvilket betyder, at den Order
tabel filtrerer tabellen Fulfillment
).
Relationskardinaliteten er indstillet til Many-to-many
for at understøtte lagring af dublerede OrderID
kolonneværdier i begge tabeller. I tabellen Order
kan der findes dublerede id-værdier, fordi en ordre kan have flere linjer. I tabellen Fulfillment
kan der findes dublet-id-værdier, fordi ordrer kan have flere linjer, og ordrelinjer kan opfyldes af mange forsendelser.
Lad os nu se på tabelrækkerne. I tabellen Fulfillment
kan du se, at ordrelinjerne kan opfyldes af flere forsendelser. (Fraværet af en ordrelinje betyder, at ordren endnu ikke er opfyldt).
Rækkedetaljerne for de to tabeller er beskrevet på følgende punktopstilling:
- Tabellen
Order
indeholder fem rækker:-
OrderDate
. januar 2019,OrderID
1,OrderLine
1,ProductID
Prod-A-,OrderQuantity
5,Sales
50 -
OrderDate
. januar 2019,OrderID
1,OrderLine
2,ProductID
Prod-B-,OrderQuantity
10,Sales
80 -
OrderDate
. februar 2019,OrderID
2,OrderLine
1,ProductID
Prod-B-,OrderQuantity
5Sales
40 -
OrderDate
. februar 2019,OrderID
2,OrderLine
2,ProductID
Prod-C,OrderQuantity
1Sales
20 -
OrderDate
. marts 2019,OrderID
3,OrderLine
1,ProductID
Prod-C-,OrderQuantity
5,Sales
100
-
- Tabellen
Fulfillment
indeholder fire rækker:-
FulfillmentDate
. 1. januar 2019FulfillmentID
50OrderID
1OrderLine
1FulfillmentQuantity
2 -
FulfillmentDate
. februar 2019,FulfillmentID
51,OrderID
2,OrderLine
1FulfillmentQuantity
5 -
FulfillmentDate
. februar 2019FulfillmentID
52OrderID
1OrderLine
1FulfillmentQuantity
3 -
FulfillmentDate
. januar 2019,FulfillmentID
53,OrderID
1,OrderLine
2FulfillmentQuantity
10
-
Lad os se, hvad der sker, når der sendes en forespørgsel til modellen. Her er en tabelvisualisering, der sammenligner ordre- og opfyldelsesmængder efter den Order
tabel OrderID
kolonne.
Visualiseringen præsenterer et nøjagtigt resultat. Modellens anvendelighed er dog begrænset, fordi du kun kan filtrere eller gruppere efter den Order
tabel OrderID
kolonne.
Vejledning til relater mange til mange-fakta
Generelt anbefaler vi ikke, at du relaterer to faktatabeller direkte ved hjælp af mange til mange-kardinalitet. Hovedårsagen er, at modellen ikke giver fleksibilitet i den måde, dine rapportvisualiseringer filtrerer eller grupperer på. I eksemplet er det kun muligt for visualiseringer at filtrere eller gruppere efter den Order
tabel OrderID
kolonne. En anden årsag er kvaliteten af dine data. Hvis dine data har integritetsproblemer, er det muligt, at nogle rækker udelades under forespørgsler på grund af kardinaliteten for mange til mennesker og begrænsede relationer.
I stedet for at relaterer faktatabeller direkte anbefaler vi, at du implementerer et stjerneskema design. Det betyder, at du tilføjer dimensionstabeller. Disse dimensionstabeller relaterer derefter til faktatabellerne ved hjælp af en til mange-relationer. Denne designtilgang er robust, da den effektivt leverer fleksible rapporteringsmuligheder. Det giver dig mulighed for at filtrere eller gruppere ved hjælp af en af kolonnerne i dimensionstabellen og opsummere kolonner i en relateret faktatabel.
Lad os overveje en bedre løsning.
Bemærk følgende designændringer:
- Modellen indeholder nu fire ekstra tabeller:
OrderLine
,OrderDate
,Product
ogFulfillmentDate
. - De fire ekstra tabeller er alle dimensionstabeller, hvor en til mange-relationer relaterer dem til faktatabellerne.
- Tabellen
OrderLine
indeholder kolonnenOrderLineID
, som gemmer denOrderID
værdi ganget med 100 plus denOrderLine
kolonneværdi – et id for hver ordrelinje. - Tabellerne
Order
ogFulfillment
indeholder nu hver især enOrderLineID
kolonne, og de indeholder ikke længere kolonnerneOrderID
ogOrderLine
. - Tabellen
Fulfillment
indeholder nuOrderDate
ogProductID
kolonner. - Tabellen
FulfillmentDate
har kun en relation til tabellenFulfillment
. - Alle id-kolonner er skjult.
Hvis du tager dig tid til at bruge et stjerneskemadesign, får du følgende fordele:
- Dine rapportvisualiseringer kan filtrere eller gruppere efter en hvilken som helst synlig kolonne fra dimensionstabellerne.
- Dine rapportvisualiseringer kan opsummere en hvilken som helst synlig kolonne fra faktatabellerne.
- Filtre, der er anvendt på tabellerne
OrderLine
,OrderDate
ellerProduct
, overføres til begge faktatabeller. - Alle relationer er en til mange-relationer, og hver relation er en almindelig relation. Problemer med dataintegritet maskeres ikke. Du kan få flere oplysninger om evaluering af relationer under Modelrelationer i Power BI Desktop.
Relater fakta om højere detaljering
Dette mange til mange-scenarie er meget forskelligt fra de to andre, der allerede er beskrevet i denne artikel.
Lad os se på et eksempel, der omfatter fire tabeller: Date
, Sales
, Product
og Target
. Tabellerne Date
og Product
er dimensionstabeller, og en til mange-relationer relaterer hver til den Sales
faktatabel. Indtil videre repræsenterer det et godt stjerneskemadesign. Den Target
tabel er dog endnu ikke relateret til de andre tabeller.
Tabellen Target
indeholder tre kolonner: Category
, TargetQuantity
og TargetYear
. Tabelrækkerne viser en granularitet på år og produktkategori. Med andre ord angives mål – der bruges til at måle salgsresultatet – hvert år for hver produktkategori.
Da der i tabellen Target
gemmes data på et højere niveau end dimensionstabellerne, kan der ikke oprettes en en til mange-relation. Det er sandt for en af relationerne. Lad os undersøge, hvordan tabellen Target
kan relaterer til dimensionstabellerne.
Relater tidsperioder med højere detaljering
En relation mellem tabellerne Date
og Target
skal være en en til mange-relation. Det skyldes, at de TargetYear
kolonneværdier er datoer. I dette eksempel gemmer hver TargetYear
kolonne den første dato i målåret.
Drikkepenge
Når du gemmer fakta med en højere tidsgranularitet end dag, skal du angive kolonnedatatypen til Dato (eller Heltal, hvis du bruger datonøgler). I kolonnen skal du gemme en værdi, der repræsenterer den første dag i tidsperioden. En årsperiode registreres f.eks. som 1. januar i året, og en månedsperiode registreres som den første dag i den pågældende måned.
Der skal dog udvises forsigtighed for at sikre, at filtre på måneds- eller datoniveau giver et meningsfuldt resultat. Uden nogen særlig beregningslogik kan rapportvisualiseringer rapportere, at måldatoer bogstaveligt talt er den første dag i hvert år. Alle andre dage – og alle måneder undtagen januar – opsummerer målantallet som BLANK.
Følgende matrixvisualisering viser, hvad der sker, når rapportbrugeren foretager detailudledning fra et år til sine måneder. Visualiseringen opsummerer kolonnen TargetQuantity
. Indstillingen Vis elementer uden data er aktiveret for matrixrækkerne.
For at undgå denne funktionsmåde anbefaler vi, at du styrer opsummering af dine faktadata ved hjælp af målinger. En måde at styre opsummering på er ved at returnere BLANK, når der forespørges om tidsperioder på lavere niveau. En anden måde– defineret med nogle avancerede DAX – er at fordele værdier på tværs af tidsperioder på lavere niveau.
Overvej følgende målingsdefinition, der bruger funktionen ISFILTERED DAX. Den returnerer kun en værdi, når kolonnerne Date
og Month
ikke filtreres.
Target Quantity =
IF(
NOT ISFILTERED('Date'[Date])
&& NOT ISFILTERED('Date'[Month]),
SUM(Target[TargetQuantity])
)
Følgende matrixvisualisering bruger målingen Target Quantity
. Det viser, at alle månedlige målantal er TOMME.
Relater højere detaljering (ikke-dato)
Der kræves en anden designtilgang, når du relaterer en ikke-datokolonne fra en dimensionstabel til en faktatabel (og den er mere detaljeret end dimensionstabellen).
De Category
kolonner (både fra tabellerne Product
og Target
) indeholder dubletværdier. Så der er ingen "en"-side for en en til mange-relation. I dette tilfælde skal du oprette en mange til mange-relation. Relationen skal overføre filtre i en enkelt retning fra dimensionstabellen til faktatabellen.
Lad os nu se på tabelrækkerne.
I tabellen Target
er der fire rækker: to rækker for hvert målår (2019 og 2020) og to kategorier (Tøj og Tilbehør). I tabellen Product
er der tre produkter. To tilhører tøjkategorien, og den ene tilhører kategorien tilbehør. En af tøjfarverne er grøn, og de resterende to er blå.
Et tabelvisual gruppering efter kolonnen Category
fra tabellen Product
giver følgende resultat. Dette visuelle element giver dog det korrekte resultat. Lad os nu overveje, hvad der sker, når kolonnen Color
fra tabellen Product
bruges til at gruppere målantal.
Visualiseringen giver en forkert gengivelse af dataene. Hvad sker der her?
Et filter på kolonnen Color
fra tabellen Product
resulterer i to rækker. En af rækkerne er for kategorien Beklædning, og den anden er til kategorien Tilbehør. Disse to kategoriværdier overføres som filtre til tabellen Target
. Da farven blå med andre ord bruges af produkter fra to kategorier, disse kategorier bruges til at filtrere målene.
For at undgå denne funktionsmåde, som beskrevet tidligere, anbefaler vi, at du styrer opsummering af dine faktadata ved hjælp af målinger.
Overvej følgende målingsdefinition. Bemærk, at alle Product
tabelkolonner, der er under kategoriniveauet, testes for filtre.
Target Quantity =
IF(
NOT ISFILTERED('Product'[ProductID])
&& NOT ISFILTERED('Product'[Product])
&& NOT ISFILTERED('Product'[Color]),
SUM(Target[TargetQuantity])
)
I følgende tabelvisualisering bruges Target Quantity
målingen. Det viser, at alle farvemålantal er TOMME.
Det endelige modeldesign ser ud som følger.
Relater vejledning til fakta med højere detaljering
Når du har brug for at relatere en dimensionstabel til en faktatabel, og faktatabellen gemmer rækker med en højere detaljeringsværdi end rækkerne i dimensionstabellen, skal du følge denne vejledning:
-
For faktadatoer med højere detaljeringstal
- I faktatabellen skal du gemme den første dato i tidsperioden.
- Opret en en til mange-relation mellem datotabellen og faktatabellen.
-
For andre fakta med højere detaljering
- Opret en mange til mange-relation mellem dimensionstabellen og faktatabellen.
-
Begge typer
- Kontrollér opsummering med målingslogik – returner BLANK, når dimensionskolonner på lavere niveau bruges til at filtrere eller gruppere.
- Skjul kolonner i faktatabellen, der kan opsummeres – som sikrer, at det kun er målinger, der kan bruges til at opsummere faktatabellen.
Relateret indhold
Du kan få flere oplysninger, der er relateret til denne artikel, i følgende ressourcer: