Del via


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 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.

diagram, der viser tre modeltabeller. Designet er beskrevet i følgende afsnit.

Den første tabel kaldes Accountog indeholder to kolonner: AccountID og Account. Den anden tabel kaldes AccountCustomerog indeholder to kolonner: AccountID og CustomerID. Den tredje tabel hedder Customerog 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.

diagram, der viser, at et modeldiagram, der består af fire tabeller. Der er tilføjet en til mange-relationer for at relatere alle tabeller.

Modeldiagrammet er blevet ændret for at hjælpe med at beskrive, hvordan overførsel af relationsfiltre fungerer, for at vise tabelrækkerne.

diagram, der viser modeltabellerne og deres rækker. Rækkedetaljerne for de fire tabeller er beskrevet i følgende afsnit.

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 til CustomerID91
    • AccountID 1 er knyttet til CustomerID92
    • AccountID 2 er knyttet til CustomerID92
  • Tabellen Transaction indeholder tre rækker:
    • Date . januar 2019AccountID1Amount100
    • Date . februar 2019AccountID2Amount200
    • Date . marts 2019AccountID1Amount-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.

diagram, der viser to tabelvisualiseringer, der sidder side om side. Visualiseringerne er beskrevet i følgende afsnit.

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.

diagram, der viser, at modellen er blevet opdateret. Den filtrerer nu i begge retninger.

diagram, der viser de samme to rapportvisualiseringer, der sidder side om side. Den første visualisering er ikke ændret, mens den anden visualisering er ændret.

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).

diagram, der viser en model, der indeholder to tabeller: Ordre og Opfyldelse.

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).

diagram, der viser rækkerne i modeltabellen. Rækkedetaljerne for de to tabeller er beskrevet i følgende afsnit.

Rækkedetaljerne for de to tabeller er beskrevet på følgende punktopstilling:

  • Tabellen Order indeholder fem rækker:
    • OrderDate . januar 2019, OrderID1, OrderLine1, ProductIDProd-A-, OrderQuantity5, Sales50
    • OrderDate . januar 2019, OrderID1, OrderLine2, ProductIDProd-B-, OrderQuantity10, Sales80
    • OrderDate . februar 2019, OrderID2, OrderLine1, ProductIDProd-B-, OrderQuantity5Sales40
    • OrderDate . februar 2019, OrderID2, OrderLine2, ProductIDProd-C, OrderQuantity1Sales20
    • OrderDate . marts 2019, OrderID3, OrderLine1, ProductIDProd-C-, OrderQuantity5, Sales100
  • Tabellen Fulfillment indeholder fire rækker:
    • FulfillmentDate . 1. januar 2019FulfillmentID50OrderID1OrderLine1FulfillmentQuantity2
    • FulfillmentDate . februar 2019, FulfillmentID51, OrderID2, OrderLine1FulfillmentQuantity5
    • FulfillmentDate . februar 2019FulfillmentID52OrderID1OrderLine1FulfillmentQuantity3
    • FulfillmentDate . januar 2019, FulfillmentID53, OrderID1, OrderLine2FulfillmentQuantity10

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.

diagram, der viser en tabelvisualisering med tre kolonner: OrderID, OrderQuantity og FulfillmentQuantity.

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.

diagram, der viser en model, der består af seks tabeller: Ordrelinje, Ordredato, Ordre, Opfyldelsesdato, Produkt og Opfyldelsesdato.

Bemærk følgende designændringer:

  • Modellen indeholder nu fire ekstra tabeller: OrderLine, OrderDate, Productog FulfillmentDate.
  • De fire ekstra tabeller er alle dimensionstabeller, hvor en til mange-relationer relaterer dem til faktatabellerne.
  • Tabellen OrderLine indeholder kolonnen OrderLineID, som gemmer den OrderID værdi ganget med 100 plus den OrderLine kolonneværdi – et id for hver ordrelinje.
  • Tabellerne Order og Fulfillment indeholder nu hver især en OrderLineID kolonne, og de indeholder ikke længere kolonnerne OrderID og OrderLine.
  • Tabellen Fulfillment indeholder nu OrderDate og ProductID kolonner.
  • Tabellen FulfillmentDate har kun en relation til tabellen Fulfillment.
  • 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, OrderDateeller Product, 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, Productog 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.

diagram, der viser en model, der består af fire tabeller: Dato, Salg, Produkt og Mål.

Tabellen Target indeholder tre kolonner: Category, TargetQuantityog 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.

diagram, der viser faktatabellerne Salg og Mål. Faktatabellen Target indeholder tre kolonner: TargetYear, Category og TargetQuantity.

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.

diagram, der viser en matrixvisualisering, der viser målantallet for år 2020 som 270. Den producerer forkerte værdier efter dato.

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.

diagram, der viser to matrixvisualiseringer. Den første viser det første månedsmål for 2020 som 270, mens den anden er tom.

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.

diagram, der viser en model af tabellerne Mål og Produkt. En mange til mange-relation relaterer de to tabeller.

Lad os nu se på tabelrækkerne.

diagram, der viser en model, der indeholder to tabeller: Mål og Produkt. En mange til mange-relation relaterer de to kolonner Kategori.

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.

diagram, der viser to tabelvisualiseringer. De første grupperer efter Kategori og den anden grupper efter Farve. Den anden visualisering giver et forkert resultat.

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.

diagram, der viser to tabelvisualiseringer. De første grupperer efter Kategori og den anden grupper efter Farve. Den anden visualisering giver et korrekt resultat af tom.

Det endelige modeldesign ser ud som følger.

diagram, der viser en model med tabellerne Date og Target, der er relateret til en en til mange-relation.

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.

Du kan få flere oplysninger, der er relateret til denne artikel, i følgende ressourcer: