Vejledning til mange til mange-relationer
Denne artikel henvender sig til dig som datamodel, 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.
Bemærk
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 .
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 faktisk tre mange til mange-scenarier. De kan forekomme, når du skal:
- Relater to tabeller af dimensionstypen
- Relater to tabeller af faktatypen
- Relater tabeller af faktatypen med højere detaljering, når tabellen af faktatypen gemmer rækker med et højere detaljeringstegn end rækkerne i tabellen af dimensionstypen
Bemærk
Power BI understøtter nu oprindeligt mange til mange-relationer. Du kan finde flere oplysninger under Anvend mange til mange-relationer i Power BI Desktop.
Relater mange til mange-dimensioner
Lad os se på den første mange til mange-scenarietype med et eksempel. Det klassiske scenarie relaterer to enheder: 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 for indehavere af fælles konti.
Modellering af disse enheder er ligetil. En tabel af dimensionstypen gemmer konti, og en anden tabel af dimensionstypen gemmer kunder. Som det er karakteristisk for tabeller af dimensionstypen, er der en id-kolonne 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 modeldiagram over de tre tabeller.
Den første tabel hedder Account og indeholder to kolonner: AccountID og Account. Den anden tabel hedder 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 tabel af faktatypen Med navnet Transaktion . Den registrerer kontotransaktioner. Brotabellen og alle id-kolonner 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.
Bemærk
Det er ikke muligt at få vist tabelrækker i Power BI Desktop-modeldiagrammet. Det gøres i denne artikel for at understøtte diskussionen med tydelige eksempler.
Rækkedetaljerne for de fire tabeller er beskrevet på følgende punktopstilling:
- Tabellen Konto indeholder to rækker:
- AccountID 1 er for Account-01
- AccountID 2 er for Account-02
- Tabellen Kunde indeholder to rækker:
- CustomerID 91 er for Customer-91
- CustomerID 92 er for Customer-92
- Tabellen AccountCustomer indeholder tre rækker:
- AccountID 1 er knyttet til CustomerID 91
- AccountID 1 er knyttet til CustomerID 92
- AccountID 2 er knyttet til CustomerID 92
- Tabellen Transaktion indeholder tre rækker:
- Dato 1. januar 2019, Konto-id 1, Beløb 100
- Dato 2. februar 2019, Konto-id 2, Beløb 200
- Dato 3. marts 2019, Konto-id 1, Beløb -25
Lad os se, hvad der sker, når der sendes en forespørgsel til modellen.
Nedenfor er to visualiseringer, der opsummerer kolonnen Amount fra tabellen Transaction . Den første visualisering grupperes efter konto, så summen af kolonnerne Beløb repræsenterer kontosaldoen. Den anden visualisering grupperes efter kunde, så summen af kolonnerne Beløb repræsenterer kundesaldoen.
Den første visualisering har titlen Kontosaldo og har to kolonner: Konto og Beløb. Det viser følgende resultat:
- Konto-01 saldobeløbet er 75
- Konto-02 saldobeløbet er 200
- Totalen er 275
Den anden visualisering har titlen Kundesaldo og har to kolonner: Kunde og Beløb. Det viser følgende resultat:
- Kunde-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 tabellen Transaktion for den pågældende konto.
Noget ser dog ikke korrekt ud med visualiseringen Kundesaldo . Hver kunde i visualiseringen Kundesaldo har 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. Problemet er relateret til filteroverførsel. Det flyder ikke hele vejen til tabellen Transaktion .
Følg filterretningerne for relationen fra tabellen Kunde til tabellen Transaktion . Det skal være tydeligt, at relationen mellem tabellen Account og AccountCustomer overføres i den forkerte retning. Filterretningen for denne relation skal angives til Begge.
Som forventet er der ikke foretaget nogen ændring af visualiseringen Kontosaldo .
Visualiseringerne 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 visualiseringens total 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, og kundesaldiene er derfor ikke-additive.
Vejledning til relater mange til mange-dimensioner
Når du har en mange til mange-relation mellem tabeller af dimensionstypen, giver vi følgende vejledning:
- Tilføj hvert mange til mange-relateret objekt som en modeltabel for at sikre, at den har en entydig identifikatorkolonne (id)
- Tilføj en mellemtabel for at gemme tilknyttede objekter
- Opret en til mange-relationer mellem de tre tabeller
- Konfigurer én tovejsrelation for at tillade filteroverførsel at fortsætte til tabeller af faktatypen
- Når det ikke er hensigtsmæssigt at have manglende id-værdier, skal du angive egenskaben Er Nullable for id-kolonner til FALSK. Dataopdateringen mislykkes, hvis manglende værdier hentes
- Skjul brotabellen (medmindre den indeholder yderligere kolonner eller målinger, der kræves til rapportering)
- Skjul alle id-kolonner, der ikke er egnede til rapportering (f.eks. når id'er er surrogatnøgler)
- Hvis det giver mening at lade en id-kolonne være synlig, skal du sørge for, at den er på "en"-sliden i relationen – skjul altid kolonnen "mange". Det resulterer i den bedste 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 visualiseringsheader
Vi anbefaler ikke, at du relaterer tabeller af dimensionstypen mange til mange 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 indeholder dubletværdier. Det er dog en vel accepteret designpraksis, at tabeller af dimensionstypen har en id-kolonne. Tabeller af dimensionstypen skal altid bruge kolonnen ID som "en"-siden af en relation.
Relater mange til mange-fakta
Den anden mange til mange-scenarietype omfatter relatering af to tabeller af faktatypen. To tabeller af faktatypen 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 tabeller af faktatypen: Ordre og Opfyldelse. Tabellen Ordre indeholder én række pr. ordrelinje, og tabellen Opfyldelse kan indeholde nul eller flere rækker pr. ordrelinje. Rækker i tabellen Ordre repræsenterer salgsordrer. Rækker i tabellen Opfyldelse repræsenterer ordreelementer, der er leveret. En mange til mange-relation relaterer de to OrderID-kolonner, hvor filteroverførsel kun er fra tabellen Ordre (Ordrefiltre Opfyldelse).
Relationskardinaliteten er angivet til mange til mange for at understøtte lagring af dublerede OrderID-værdier i begge tabeller. I tabellen Order kan der findes dublerede OrderID-værdier , fordi en ordre kan have flere linjer. I tabellen Opfyldelse kan der findes dubletværdier for Ordre-id , fordi ordrer kan have flere linjer, og ordrelinjer kan opfyldes af mange leverancer.
Lad os nu se på tabelrækkerne. Bemærk, at ordrelinjer kan opfyldes af flere leverancer i tabellen Opfyldelse. (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:
- Ordredato 1. januar 2019, Ordre-id 1, Ordrelinje 1, Produkt-id Prod-A, Ordreantal 5, Salg 50
- Ordredato 1. januar 2019, Ordre-id 1, Ordrelinje 2, Produkt-ID Prod-B, Ordreantal 10, Salg 80
- Ordredato 2. februar 2019, Ordre-id 2, Ordrelinje 1, Produkt-id Prod-B, Ordreantal 5, Salg 40
- Ordredato 2. februar 2019, Ordre-id 2, Ordrelinje 2, Produkt-ID Prod-C, Ordreantal 1, Salg 20
- Ordredato 3. marts 2019, Ordre-id 3, Ordrelinje 1, Produkt-id Prod-C, Ordreantal 5, Salg 100
- Tabellen Opfyldelse indeholder fire rækker:
- Opfyldelsesdato 1. januar 2019, Opfyldelses-id 50, Ordre-id 1, Ordrelinje 1, Opfyldelsesantal 2
- Opfyldelsesdato 2. februar 2019, Opfyldelses-id 51, Ordre-id 2, Ordrelinje 1, Opfyldelsesantal 5
- Opfyldelsesdato 2. februar 2019, Opfyldelses-id 52, Ordre-id 1, Ordrelinje 1, Opfyldelsesantal 3
- Opfyldelsesdato 1. januar 2019, Opfyldelses-id 53, Ordre-id 1, Ordrelinje 2, Opfyldelsesantal 10
Lad os se, hvad der sker, når der sendes en forespørgsel til modellen. Her er en tabelvisualisering, der sammenligner ordre- og opfyldelsesantal med kolonnen Ordretabel - Ordre-id .
Visualiseringen præsenterer et nøjagtigt resultat. Modellens anvendelighed er dog begrænset – du kan kun filtrere eller gruppere efter kolonnen Order table OrderID .
Vejledning til relater mange til mange-fakta
Generelt anbefaler vi ikke, at du relaterer to tabeller af faktatypen direkte ved hjælp af mange til mange-kardinalitet. Hovedårsagen er, at modellen ikke giver fleksibilitet i den måde, du rapporterer visualiseringer på, filtrerer eller grupperer. I eksemplet er det kun muligt for visualiseringer at filtrere eller gruppere efter kolonnen Order table OrderID . En yderligere å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 arten af den begrænsede relation. Du kan få flere oplysninger under Modelrelationer i Power BI Desktop (evaluering af relationer).
I stedet for at relaterer tabeller af faktatypen direkte, anbefaler vi, at du anvender principper for design af stjerneskemaer . Det gør du ved at tilføje tabeller af dimensionstypen. Tabellerne af dimensionstypen relaterer derefter til tabeller af faktatypen ved hjælp af en til mange-relationer. Denne designtilgang er robust, da den giver fleksible rapporteringsmuligheder. Det giver dig mulighed for at filtrere eller gruppere ved hjælp af kolonner af dimensionstypen og opsummere alle relaterede tabeller af faktatypen.
Lad os overveje en bedre løsning.
Bemærk følgende designændringer:
- Modellen har nu fire ekstra tabeller: Ordrelinje, Ordredato, Produkt og Opfyldelsesdato
- De fire ekstra tabeller er alle tabeller af dimensionstypen, og en til mange-relationer relaterer disse tabeller til tabeller af faktatypen
- Tabellen OrderLine indeholder kolonnen OrderLineID , som repræsenterer værdien OrderID ganget med 100 plus værdien Ordrelinje – et entydigt id for hver ordrelinje
- Tabellerne Ordre og Opfyldelse indeholder nu kolonnen Ordrelinje-id, og de indeholder ikke længere kolonnerne Ordre-id og Ordrelinje
- Tabellen Opfyldelse indeholder nu kolonnerne OrderDate og ProductID
- Tabellen Opfyldelsesdato er kun relateret til tabellen Opfyldelse
- Alle entydige id-kolonner er skjult
Hvis du tager dig tid til at anvende designprincipper for stjerneskemaer, får du følgende fordele:
- Dine rapportvisualiseringer kan filtrere eller gruppere efter en hvilken som helst synlig kolonne fra tabeller af dimensionstypen
- Dine rapportvisualiseringer kan opsummere en hvilken som helst synlig kolonne fra tabeller af faktatypen
- Filtre, der anvendes på tabellerne OrderLine, OrderDate eller Product , overføres til begge tabeller af faktatypen
- Alle relationer er en til mange-relationer, og hver relation er en almindelig relation. Problemer med dataintegritet maskeres ikke. Du kan få flere oplysninger under Modelrelationer i Power BI Desktop (evaluering af relationer).
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: Dato, Salg, Produkt og Mål. Dato og produkt er tabeller af dimensionstypen, og en til mange-relationer relaterer hver til tabellen Sales-faktatype. Indtil videre repræsenterer det et godt stjerneskemadesign. Tabellen Target 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 Mål gemmes data på et højere niveau end tabeller af dimensionstypen, kan der ikke oprettes en en til mange-relation. Det er sandt for en af relationerne. Lad os undersøge, hvordan tabellen Mål kan relaterer til tabeller af dimensionstypen.
Relater tidsperioder med højere detaljering
En relation mellem tabellerne Date og Target skal være en en til mange-relation. Det skyldes, at kolonneværdierne for TargetYear er datoer. I dette eksempel er hver værdi i kolonnen TargetYear den første dato i målåret.
Tip
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 . (Den Vis elementer uden dataindstilling 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 DAX-funktionen ISFILTERED . Den returnerer kun en værdi, når kolonnerne Dato eller Måned ikke filtreres.
Target Quantity =
IF(
NOT ISFILTERED('Date'[Date])
&& NOT ISFILTERED('Date'[Month]),
SUM(Target[TargetQuantity])
)
Følgende matrixvisualisering bruger nu målingen Målantal . 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 tabel af dimensionstypen til en tabel af faktatypen (og den er mere detaljeret end tabellen af dimensionstypen).
Kolonnerne Kategori (fra tabellerne Product og Target ) indeholder dublerede værdier. Så der er ingen "en" 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 tabellen af dimensionstypen til tabellen af faktatypen.
Lad os nu se på tabelrækkerne.
I tabellen Mål 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 Produkt 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å.
En tabelvisualisering efter kolonnen Kategori fra tabellen Product giver følgende resultat.
Denne visualisering giver 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 Mål . Da farven blå med andre ord bruges af produkter fra to kategorier, bruges disse kategorier 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 kolonner i tabellen Product , 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 målingen Målantal nu. 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 tabel af dimensionstypen til en tabel af faktatypen, og tabellen af faktatypen gemmer rækker med et højere detaljeringstegn end rækkerne i tabellen af dimensionstypen, giver vi følgende vejledning:
- For faktadatoer med højere detaljering:
- I tabellen af faktatypen skal du gemme den første dato i tidsperioden
- Opret en en til mange-relation mellem datotabellen og tabellen af faktatypen
- For andre fakta med højere detaljering:
- Opret en mange til mange-relation mellem tabellen af dimensionstypen og tabellen af faktatypen
- For begge typer:
- Kontrollér opsummering med målingslogik – returner BLANK, når kolonner af dimensionstypen på lavere niveau bruges til at filtrere eller gruppere
- Skjul tabelkolonner af faktatypen, der kan opsummeres – på denne måde kan kun målinger bruges til at opsummere tabellen af faktatypen
Relateret indhold
Du kan få flere oplysninger, der er relateret til denne artikel, i følgende ressourcer: