Jaa


ORDERBY-, PARTITIONBY- ja MATCHBY-funktioiden ymmärtäminen

DAX ORDERBY-, PARTITIONBY- ja MATCHBY-funktiot ovat erikoisfunktioita, joita voidaan käyttää vain DAX -ikkunafunktioiden kanssa: INDEX, OFFSET, WINDOW, RANK, ROWNUMBER.

On tärkeää ymmärtää ORDERBY, PARTITIONBYja MATCHBY, jotta voit käyttää Window-funktioita. Tässä esitetyissä esimerkeissä käytetään OFFSET, mutta niitä voidaan soveltaa samoin kuin muita Window-funktioita.

Skenaario

Aloitetaan esimerkistä, jossa ei käytetä Ikkuna-funktioita lainkaan. Alla on taulukko, joka palauttaa kokonaismyynnin väriä ja kalenterivuotta kohden. Tämä taulukko voidaan määrittää monella tavalla, mutta koska olemme kiinnostuneita siitä, mitä DAXtapahtuu, käytämme laskettua taulukkoa. Tässä on taulukkolauseke:

BasicTable = 
    SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
    )

Näet, että tämä laskettu taulukkolauseke käyttää SUMMARIZECOLUMNS Laskettaessa FactInternetSales-taulukon SalesAmount-sarakkeen SUM DimProduct-taulukon Color-sarakkeen ja DimDate-taulukon CalendarYear-sarakkeen mukaan. Tässä on tulos:

Väri Kalenterivuosi CurrentYearSales
"Musta" 2017 393885
"Musta" 2018 1818835
"Musta" 2019 3981638
"Musta" 2020 2644054
"Sininen" 2019 994448
"Sininen" 2020 1284648
"Moni" 2019 48622
"Moni" 2020 57849
"NA" 2019 207822
"NA" 2020 227295
"Punainen" 2017 2961198
"Punainen" 2018 3686935
"Punainen" 2019 900175
"Punainen" 2020 176022
"Hopeinen" 2017 326399
"Hopeinen" 2018 750026
"Hopeinen" 2019 2165176
"Hopeinen" 2020 1871788
"Valkoinen" 2019 2517
"Valkoinen" 2020 2589
"Keltainen" 2018 163071
"Keltainen" 2019 2072083
"Keltainen" 2020 2621602

Ajatellaanpa, että yritämme ratkaista liiketoimintakysymystä, joka koskee myynnin eron laskemista vuoden aikana kullekin värille. Käytännössä tarvitset tavan löytää edellisen vuoden saman värisen myynnin ja vähentää sen nykyisen vuoden myynnistä kontekstissa. Esimerkiksi yhdistelmälle [Red, 2019] etsitään myyntiä tuotteille [Red, 2018]. Kun se on saatu, voimme vähentää sen nykyisestä myynnistä ja palauttaa vaaditun arvon.

OFFSET käyttäminen

OFFSET sopii täydellisesti tyypillisiin verrattuna aiempiin laskutoimitusten tyyppeihin, joita tarvitaan edellä kuvattuun liiketoimintakysymykseen vastaamiseksi, koska se mahdollistaa suhteellisen liikkumisen. Ensimmäinen yrityksemme voi olla:

1stAttempt = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS (
        vRelation,
        "PreviousColorSales",
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation
            ),
            [CurrentYearSales]
        )
    )

Tällä lausekkeella tapahtuu paljon. Käytimme ADDCOLUMNS taulukon laajentamiseen aiempaan sarakkeella nimeltä PreviousColorSales. Kyseisen sarakkeen sisällöksi määritetään CurrentYearSales, joka on SUM(FactInternetSales[SalesAmount]) edelliselle värille (noudettu käyttämällä OFFSET).

Tulos on:

Väri Kalenterivuosi CurrentYearSales PreviousColorSales
"Musta" 2017 393885
"Musta" 2018 1818835 393885
"Musta" 2019 3981638 1818835
"Musta" 2020 2644054 3981638
"Sininen" 2019 994448 2644054
"Sininen" 2020 1284648 994448
"Moni" 2019 48622 1284648
"Moni" 2020 57849 48622
"NA" 2019 207822 57849
"NA" 2020 227295 207822
"Punainen" 2017 2961198 227295
"Punainen" 2018 3686935 2961198
"Punainen" 2019 900175 3686935
"Punainen" 2020 176022 900175
"Hopeinen" 2017 326399 176022
"Hopeinen" 2018 750026 326399
"Hopeinen" 2019 2165176 750026
"Hopeinen" 2020 1871788 2165176
"Valkoinen" 2019 2517 1871788
"Valkoinen" 2020 2589 2517
"Keltainen" 2018 163071 2589
"Keltainen" 2019 2072083 163071
"Keltainen" 2020 2621602 2072083

Tämä on yksi askel lähempänä tavoitettamme, mutta jos katsomme tarkasti, se ei vastaa tarkalleen mitä haluamme. Esimerkiksi kaavalle [Silver, 2017] PreviousColorSales on määritetty arvoksi [Red, 2020].

ORDERBY lisääminen

Edellä oleva määritelmä vastaa:

1stAttemptWithORDERBY = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS (
        vRelation,
        "PreviousColorSales",
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation,
                ORDERBY ([Color], ASC, [CalendarYear], ASC, [CurrentYearSales], ASC)
            ),
            [CurrentYearSales]
        )
    )

Tässä tapauksessa OFFSET kutsu käyttää ORDERBY järjestääkseen taulukon Color- ja CalendarYear-funktioiden mukaan nousevassa järjestyksessä, mikä määrittää, mitä pidetään edellisenä palautettavana rivinä.

Nämä kaksi tulosta vastaavat toisiaan, koska ORDERBY sisältää automaattisesti kaikki vertailun sarakkeet, jotka eivät ole PARTITIONBY. Koska PARTITIONBY ei määritetty, ORDERBY on määritetty arvoksi Väri, Kalenterivuosi ja CurrentYearSales. Koska väri- ja kalenterivuosiparit suhteessa ovat kuitenkin yksilöllisiä, CurrentYearSales-sarakkeen lisääminen ei muuta tulosta. Vaikka määrittäisit värin vain ORDERBY, tulokset ovat samat, koska Kalenterivuosi lisätään automaattisesti. Tämä johtuu siitä, että funktio lisää niin monta saraketta kuin tarvitaan ORDERBY, jotta ORDERBY ja PARTITIONBY-sarakkeet voivat tunnistaa kunkin rivin yksilöllisesti:

1stAttemptWithORDERBY = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS(
        vRelation,
        "PreviousColorSales",
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation,
                ORDERBY ([Color])
            ),
            [CurrentYearSales]
        )
    )

PARTITIONBY lisääminen

Nyt voit lähes saada tulokseksi tuloksemme, jonka jälkeen voimme käyttää PARTITIONBY, seuraavassa lasketun taulukon lausekkeessa esitetyllä tavalla:

UsingPARTITIONBY = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS (
        vRelation,
        "PreviousColorSales",
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation,
                ORDERBY ([CalendarYear]), 
                PARTITIONBY ([Color])
            ),
            [CurrentYearSales]
        )
    )

Huomaa, että ORDERBY määrittäminen on tässä valinnaista, koska ORDERBY sisältää automaattisesti kaikki suhteen sarakkeet, joita ei ole määritetty PARTITIONBY. Seuraava lauseke palauttaa siis samat tulokset, koska ORDERBY-arvoksi on määritetty automaattisesti CalendarYear ja CurrentYearSales:

UsingPARTITIONBYWithoutORDERBY = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS (
        vRelation,
        "PreviousColorSales",
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation,
                PARTITIONBY ([Color])
            ),
            [CurrentYearSales]
        )
    )

Muistiinpano

Vaikka ORDERBY on määritetty automaattisesti Kalenterivuosi- ja Kuluva vuosimyynti -arvoihin, niiden lisäysjärjestyksestä ei anneta mitään takuuta. Jos CurrentYearSales lisätään ennen kalenterivuotta, tuloksena saatu tilaus ei vastaa odotettua. Määritä ORDERBY ja PARTITIONBY eksplisiittisesti sekaannusten ja odottamattomien tulosten välttämiseksi.

Molemmat lausekkeet palauttavat etsimämme tuloksen:

Väri Kalenterivuosi CurrentYearSales PreviousYearSalesForSameColor
"Musta" 2017 393885
"Musta" 2018 1818835 393885
"Musta" 2019 3981638 1818835
"Musta" 2020 2644054 3981638
"Sininen" 2019 994448
"Sininen" 2020 1284648 994448
"Moni" 2019 48622
"Moni" 2020 57849 48622
"NA" 2019 207822
"NA" 2020 227295 207822
"Punainen" 2017 2961198
"Punainen" 2018 3686935 2961198
"Punainen" 2019 900175 3686935
"Punainen" 2020 176022 900175
"Hopeinen" 2017 326399
"Hopeinen" 2018 750026 326399
"Hopeinen" 2019 2165176 750026
"Hopeinen" 2020 1871788 2165176
"Valkoinen" 2019 2517
"Valkoinen" 2020 2589 2517
"Keltainen" 2018 163071
"Keltainen" 2019 2072083 163071
"Keltainen" 2020 2621602 2072083

Kuten tässä taulukossa näkyy, PreviousYearSalesForSameColor-sarake näyttää edellisen vuoden myynnin samalle värille. Funktiolle [Red, 2020] se palauttaa esimerkiksi myynnin arvolle [Red, 2019]. Jos edellistä vuotta ei ole, esimerkiksi jos kyseessä on [Red, 2017], mitään arvoa ei palauteta.

Voit ajatella PARTITIONBY keinona jakaa taulukko osiin, joissa OFFSET laskutoimitus suoritetaan. Yllä olevassa esimerkissä taulukko on jaettu niin moneen osaan kuin väreihin, yksi kuhunkin väriin. Sitten OFFSET lasketaan kunkin osan sisällä kalenterivuoden mukaan lajiteltuna.

Visuaalisesti tämä on seuraava tapahtuma:

taulukko, joka näyttää OFFSET kalenterivuoden mukaan

PARTITIONBY kutsu jakaa ensin taulukon osiin, yhden kullekin Värille. Tätä ilmaisevat taulukon kuvan vaaleansiniset ruudut. Seuraavaksi ORDERBY varmistaa, että jokainen osa lajitellaan kalenterivuoden mukaan (oranssit nuolet edustavat sitä). Lopuksi kunkin lajitellun osan sisällä kullekin riville OFFSET löytää sen yläpuolella olevan rivin ja palauttaa tämän arvon PreviousYearSalesForSameColor-sarakkeessa. Koska kunkin osan jokaisen ensimmäisen rivin kohdalla ei ole edellistä riviä samassa osassa, tämä PreviousYearSalesForSameColor-sarakkeen rivi on tyhjä.

Jotta saavutetaan lopullinen tulos, meidän on yksinkertaisesti vähennettävä CurrentYearSales edellisen vuoden myynnistä samalle värille, jonka kutsu palautti OFFSET. Koska emme halua näyttää edellisen vuoden myyntiä samalla värillä, vaan vain nykyisen vuoden myynnissä ja vuosi-erossa. Tässä on lopullinen lasketun taulukon lauseke:

FinalResult = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS (
        vRelation,
        "YoYSalesForSameColor",
        [CurrentYearSales] -
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation,
                ORDERBY ([CalendarYear]),
                PARTITIONBY ([Color])
            ),
            [CurrentYearSales]
        )
    )

Tässä on lausekkeen tulos:

Väri Kalenterivuosi CurrentYearSales YoYSalesForSameColor
"Musta" 2017 393885 393885
"Musta" 2018 1818835 1424950
"Musta" 2019 3981638 2162803
"Musta" 2020 2644054 -1337584
"Sininen" 2019 994448 994448
"Sininen" 2020 1284648 290200
"Moni" 2019 48622 48622
"Moni" 2020 57849 9227
"NA" 2019 207822 207822
"NA" 2020 227295 19473
"Punainen" 2017 2961198 2961198
"Punainen" 2018 3686935 725737
"Punainen" 2019 900175 -2786760
"Punainen" 2020 176022 -724153
"Hopeinen" 2017 326399 326399
"Hopeinen" 2018 750026 423627
"Hopeinen" 2019 2165176 1415150
"Hopeinen" 2020 1871788 -293388
"Valkoinen" 2019 2517 2517
"Valkoinen" 2020 2589 72
"Keltainen" 2018 163071 163071
"Keltainen" 2019 2072083 1909012
"Keltainen" 2020 2621602 549519

MATCHBY käyttäminen

Olet ehkä huomannut, että emme määrittäneet MATCHBY ollenkaan. Tässä tapauksessa se ei ole tarpeen. ORDERBY ja PARTITIONBY sarakkeet (yllä esimerkeissä määritetyn mukaisesti) riittävät yksilöimään kunkin rivin. Koska emme määrittäneet MATCHBY, ORDERBY määritettyjä sarakkeita ja PARTITIONBY käytetään yksilöimään kukin rivi, jotta niitä voidaan verrata siihen, OFFSET mahdollistavat merkityksellisen tuloksen. Jos ORDERBY ja PARTITIONBY sarakkeita ei pysty yksilöimään kutakin riviä, ORDERBY-lauseeseen voidaan lisätä lisäsarakkeita, jos näiden lisäsarakkeiden avulla kukin rivi voidaan tunnistaa yksilöllisesti. Jos se ei ole mahdollista, palautetaan virhe. Tässä viimeisessä tapauksessa MATCHBY määrittäminen voi auttaa ratkaisemaan virheen.

Jos MATCHBY on määritetty, MATCHBY ja PARTITIONBY sarakkeita käytetään yksilöimään kukin rivi. Jos se ei ole mahdollista, palautetaan virhe. Vaikka MATCHBY ei olisi pakollista, harkitse MATCHBY eksplisiittistä määrittämistä sekaannuksien välttämiseksi.

Yllä olevista esimerkeistä jatkaen tässä on viimeinen lauseke:

FinalResult = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS (
        vRelation,
        "YoYSalesForSameColor",
        [CurrentYearSales] -
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation,
                ORDERBY ([CalendarYear]),
                PARTITIONBY ([Color])
            ),
            [CurrentYearSales]
        )
    )

Jos haluamme määrittää tarkasti, miten rivit tulee yksilöidä, voimme määrittää MATCHBY seuraavassa vastaavassa lausekkeessa esitetyllä tavalla:

FinalResultWithExplicitMATCHBYOnColorAndCalendarYear = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS (
        vRelation,
        "YoYSalesForSameColor",
        [CurrentYearSales] -
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation,
                ORDERBY ([CalendarYear]),
                PARTITIONBY ([Color]),
                MATCHBY ([Color], [CalendarYear])
            ),
            [CurrentYearSales]
        )
    )

Koska määritetään MATCHBY, sekä MATCHBY että PARTITIONBY määritettyjä sarakkeita käytetään rivien yksilöimiseen. Koska Color määritetään sekä MATCHBY että PARTITIONBY, seuraava lauseke vastaa edellistä lauseketta:

FinalResultWithExplicitMATCHBYOnCalendarYear = 
    VAR vRelation = SUMMARIZECOLUMNS ( 
        DimProduct[Color], 
        DimDate[CalendarYear], 
        "CurrentYearSales", ROUND ( SUM ( FactInternetSales[SalesAmount] ), 0 )
        )
    RETURN
    ADDCOLUMNS (
        vRelation,
        "YoYSalesForSameColor",
        [CurrentYearSales] -
        SELECTCOLUMNS (
            OFFSET (
                -1,
                vRelation,
                ORDERBY ([CalendarYear]),
                PARTITIONBY ([Color]),
                MATCHBY ([CalendarYear])
            ),
            [CurrentYearSales]
        )
    )

Koska MATCHBY määrittäminen ei ole tarpeen esimerkeissä, joita olemme tähän mennessä tarkastelleet, katsotaanpa hieman erilaista esimerkkiä, joka edellyttää MATCHBY. Tässä tapauksessa meillä on luettelo tilausriveistä. Jokainen rivi edustaa tilauksen tilausriviä. Tilaukseen voi olla useita tilausrivejä, ja tilausrivi 1 näkyy useissa tilauksissa. Lisäksi jokaisella tilausrivillä on ProductKey- ja SalesAmount-arvot. Esimerkki taulukon asiaankuuluvista sarakkeista näyttää tältä:

SalesOrderNumber SalesOrderLineNumber Tuoteavain SalesAmount
SO51900 1 528 4.99
SO51948 1 528 5.99
SO52043 1 528 4.99
SO52045 1 528 4.99
SO52094 1 528 4.99
SO52175 1 528 4.99
SO52190 1 528 4.99
SO52232 1 528 4.99
SO52234 1 528 4.99
SO52234 2 529 3.99

Huomaa, että rivien yksilöimiseen tarvitaan sekä SalesOrderNumber että SalesOrderLineNumber.

Haluamme palauttaa kullekin tilaukselle saman tuotteen edellisen myyntisumman (jota edustaa Tuoteavain), jonka SalesAmount tilasi laskevassa järjestyksessä. Seuraava lauseke ei toimi, koska vRelationissa on mahdollisesti useita rivejä, koska se välitetään OFFSET:

ThisExpressionFailsBecauseMATCHBYIsMissing = 
    ADDCOLUMNS (
        FactInternetSales,
        "Previous Sales Amount",
            SELECTCOLUMNS (
                OFFSET (
                    -1,
                    FactInternetSales,
                    ORDERBY ( FactInternetSales[SalesAmount], DESC ),
                    PARTITIONBY ( FactInternetSales[ProductKey] )
                ),
                FactInternetSales[SalesAmount]
            )
    )

Tämä lauseke palauttaa virheen: "OFFSET:n Relation-parametrissa voi olla rivien kaksoiskappaleita, mitä ei sallita."

Jotta tämä lauseke toimisi, MATCHBY on määritettävä ja siihen on sisällytettävä kaikki sarakkeet, jotka määrittävät rivin yksilöllisesti. MATCHBY tässä vaaditaan, koska suhde FactInternetSales ei sisällä eksplisiittisiä avaimia tai yksilöllisiä sarakkeita. SalesOrderNumber- ja SalesOrderLineNumber-sarakkeet muodostavat kuitenkin yhdessä yhdistelmäavaimen, jossa niiden olemassaolo yhdessä on yksilöllinen suhteessa ja siten tunnistaa kukin rivi yksilöllisesti. Pelkkä SalesOrderNumber- tai SalesOrderLineNumber-arvon määrittäminen ei riitä, koska molemmat sarakkeet sisältävät toistuvia arvoja. Seuraava lauseke ratkaisee ongelman:

ThisExpressionWorksBecauseOfMATCHBY = 
    ADDCOLUMNS (
        FactInternetSales,
        "Previous Sales Amount",
            SELECTCOLUMNS (
                OFFSET (
                    -1,
                    FactInternetSales,
                    ORDERBY ( FactInternetSales[SalesAmount], DESC ),
                    PARTITIONBY ( FactInternetSales[ProductKey] ),
                    MATCHBY ( FactInternetSales[SalesOrderNumber], 
                                FactInternetSales[SalesOrderLineNumber] )
                ),
                FactInternetSales[SalesAmount]
            )
    )

Ja tämä lauseke todellakin palauttaa seuraamme seuraavat tulokset:

SalesOrderNumber SalesOrderLineNumber Tuoteavain SalesAmount Edellisen myynnin summa
SO51900 1 528 5.99
SO51948 1 528 4.99 5.99
SO52043 1 528 4.99 4.99
SO52045 1 528 4.99 4.99
SO52094 1 528 4.99 4.99
SO52175 1 528 4.99 4.99
SO52190 1 528 4.99 4.99
SO52232 1 528 4.99 4.99
SO52234 1 528 4.99 4.99
SO52234 2 529 3.99

ORDERBY PARTITIONBY MATCHBY INDEX OFFSET WINDOW RANK ROWNUMBER