Podstawy MDX
Transkrypt
Podstawy MDX
Podstawy MDX Podstawowe zapytanie MDX ma strukturę podobną do zapytań SQL. Najprostsza postać zwraca dwuwymiarową kostkę: SELECT opis osi ON COLUMNS, opis osi ON ROWS FROM nazwa_kostki [WHERE opis_plastra] Podstawy MDX Najprostsza postać opisu osi lub wyboru członów używa MEMBERS jako wymaganego wymiaru, łącznie ze wymiarem Measures: SELECT Measures.MEMBERS ON COLUMNS, [Nazwa kategorii].MEMBERS ON ROWS FROM [BiznesG] Opis osi może być traktowany jako wybór członu dla osi. Jeżeli wymagany jest pojedynczy wymiar, przy użyciu takiego zapisu musi być zwrócone COLUMNS. Dla większej ilości wymaganych wymiarów nazwami osi byłyby PAGES (strony), CHAPTERS (rozdziały) oraz SECTIONS (sekcje). Jeśli chcemy użyć bardziej uniwersalnych określeń osi, możemy użyć konwencji: AXIS(index), gdzie index jest zakresem rozpoczynającym się od zera. W Management Studio dopuszczalne tylko dwie osie. Podstawy MDX Jeżeli chcemy wyliczyć elementy wymiaru, mogą one być zwrócone jako pojedyncza oś (lista ograniczona {...} rozdzielona , : SELECT Measures.MEMBERS ON COLUMNS, {[Nazwa kategorii].[clocks], [Nazwa kategorii].[sampler] } ON ROWS FROM [BiznesG] Struktura kostki [BiznesG] 1 Parents ANCESTOR(Time.[2000].[Q1], Time.[Year]) Time.[2000].[Q1].Parent.Parent Time.[2000].Parent All All Time.[2001].Parent 2000 Time.[2000].[Q1].Parent Jan Descendants Descendants( Time.[2000], Quarter) 2001 Q1 Q2 Q3 Q4 Q1 Feb Mar Oct Nov Dec Q2 Q3 Q4 Jan 2000 2001 Q1 Q2 Q3 Q4 Q1 Feb Mar Oct Nov Dec Q2 Q3 Q4 Descendants( Time.[2000], Month) Children Descendants All All Time.[2000].Children Time.[2000].FirstChild Jan 2000 2000 2001 Q1 Q2 Q3 Q4 Q1 Feb Mar Oct Nov Dec Q2 Q3 Q4 Jan 2001 Q1 Q2 Q3 Q4 Q1 Feb Mar Oct Nov Dec Q2 Q3 Q4 Descendants(Time.[2000].[Jan], Month) 2 Podstawy MDX Aby uzyskać miary dla członów składających się na te kategorie, zapytalibyśmy ich dzieci (CHILDREN): SELECT Measures.MEMBERS ON COLUMNS, {[KategoriaProduktuH].[Nazwa kategorii].[clocks].CHILDREN, [KategoriaProduktuH].[Nazwa kategorii].[sampler].CHILDREN } ON ROWS FROM [BiznesG] Podstawy MDX Miary obliczane nie są dołączane, gdy pobierane są człony wymiarów. Ich uwzględnienie musi być jawnie narzucone, przez użycie funkcji ADDCALCULATEDMEMBERS:. SELECT ADDCALCULATEDMEMBERS(Measures.MEMBERS) ON COLUMNS, {[KategoriaProduktuH].[Nazwa kategorii].[clocks], DESCENDANTS( [KategoriaProduktuH].[Nazwa kategorii].[clocks],[Nazwa Towaru])}ON ROWS FROM [BiznesG] Funkcja MEMBERS zwraca elementy wskazanego wymiaru lub poziomu wymiarów. Funkcja CHILDREN zwraca dzieci dla określonego członu wymiaru. Obie funkcje są używane przy formułowaniu wyrażeń, ale nie zapewniają możliwości rozwijania do niższych poziomów hierarchii. Podstawy MDX Przy użyciu funkcji DESCENDANTS możliwe się staje zapytanie kostki o informacje na poziomie nazwa towaru dla wybranej kategorii SELECT Measures.MEMBERS ON COLUMNS, { [KategoriaProduktuH].[Nazwa kategorii].[clocks], DESCENDANTS( [KategoriaProduktuH].[Nazwa kategorii].[clocks], [Nazwa Towaru]) }ON ROWS FROM [BiznesG] Podstawy MDX Wybór miar do wyświetlenia SELECT {MEASURES.wartosc, MEASURES.zysk} ON COLUMNS, { [KategoriaProduktuH].[Nazwa kategorii].[clocks], DESCENDANTS( [KategoriaProduktuH].[Nazwa kategorii].[clocks], [Nazwa Towaru]) }ON ROWS FROM [BiznesG] DESCENDANTS(człon, poziom [, flagi]) Wartość flagi może wynosić: SELF (domyślna wartość), BEFORE, AFTER lub BEFORE_AND_AFTER 3 Podstawy MDX Zastosowanie krotki na wymiarach w celu wyświetlenia hierarchii SELECT ADDCALCULATEDMEMBERS(Measures.MEMBERS) ON COLUMNS, {CROSSJOIN( [KategoriaTowaruG].[Nazwa kategorii].members, [KategoriaProduktuH].[Nazwa Towaru].members)}ON ROWS FROM [BiznesG] Każda pozycja z jednego wymiaru z każdą z drugiego CROSSJOIN nie może być zastosowany do dwa razy występującego tego samego wymiaru Podstawy MDX Zastosowanie krotki na wymiarach w celu wyświetlenia hierarchii SELECT ADDCALCULATEDMEMBERS(Measures.MEMBERS) ON COLUMNS, { NONEMPTY (CROSSJOIN( FILTER ( [KategoriaTowaruG].[Nazwa kategorii].members, [KategoriaTowaruG].[Nazwa kategorii]<>[KategoriaTowaruG].[Nazwa kategorii].[ALL] ), [KategoriaProduktuH].[Nazwa Towaru].members)) }ON ROWS FROM [BiznesG] Wyeliminowanie elementu ALL reprezentującego wszystkie obiekty poziomu nadrzędnego osiągamy przez zastosowanie funkcji FILTER Podstawy MDX Zastosowanie krotki na wymiarach w celu wyświetlenia hierarchii SELECT ADDCALCULATEDMEMBERS(Measures.MEMBERS) ON COLUMNS, { NONEMPTY (CROSSJOIN( [KategoriaTowaruG].[Nazwa kategorii].members, [KategoriaProduktuH].[Nazwa Towaru].members)) }ON ROWS FROM [BiznesG] Podstawy MDX Nie zastosowanie krotki powoduje „spłaszczenie” wyświetlania SELECT Measures.MEMBERS ON COLUMNS, { [KategoriaProduktuH].[Nazwa kategorii].members, [KategoriaProduktuH].[Nazwa Towaru].members}ON ROWS FROM [BiznesG] W celu wyeliminowania niepowiązanych rekordów zastosować możemy operator NONEMPTY Nazwy towarów dla kategorii CLOCKS 4 Podstawy MDX Specyfikację plastra definiuje się przez klauzulę WHERE SELECT [Nazwa Kategorii].MEMBERS ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] WHERE ([Measures].[wartosc]) Podstawy MDX SELECT [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] WHERE ([Measures].[wartosc], [Towar G].[Nazwa Kategorii].[CLOCKS]) Definiowanie plastra z wykorzystaniem dwóch wymiarów zawierających ten sam poziom Mało eleganckie ze względu na wartości NULL Podstawy MDX Bardziej szczegółową definicję plastra można osiągnąć przez zdefiniowanie konkretnej wartości wymiaru SELECT [Nazwa Kategorii].MEMBERS ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] WHERE Nie można do definiowania plastra użyć wymiaru poprzednio ([Measures].[wartosc], wykorzystanego do definiowania [Data Faktury].[Rok].[2003]) kolumn lub wierszy Podstawy MDX SELECT NONEMPTY([KategoriaTowaruG].[Nazwa Kategorii].MEMBERS) ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] WHERE ([Measures].[wartosc], Definiowanie plastra z [Towar G].[Nazwa Kategorii].[CLOCKS]) wykorzystaniem dwóch wymiarów zawierających ten sam poziom Pominięcie wartości NULL przy użyciu NONEMPTY 5 Podstawy MDX SELECT [KategoriaTowaruG].[Nazwa Kategorii].[CLOCKS] ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] WHERE ([Measures].[wartosc]) Definiowanie plastra z wykorzystaniem jawnego wskazania na wartość w kolumnie Podstawy MDX Możliwe jest wyznaczenie członów wyliczanych Ad hoc przy zastosowaniu klauzuli WITH WITH MEMBER Measures.ZyskProcentowy AS '([Measures].[Wartosc] - [Measures].[WartoscZakupu]) / [Measures].[WartoscZakupu]', FORMAT_STRING = '#.00%' SELECT [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] WHERE Measures.ZyskProcentowy Podstawy MDX Możliwe jest wyznaczenie członów wyliczanych Ad hoc przy zastosowaniu klauzuli WITH oraz miary wyliczanej WITH MEMBER Measures.ZyskProcentowy AS '([Measures].[zysk]) / [Measures].[WartoscZakupu]', FORMAT_STRING = '#.00%' SELECT [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] WHERE Measures.ZyskProcentowy Podstawy MDX Możliwe jest wyznaczenie członów wyliczanych Ad hoc przy zastosowaniu klauzuli WITH WITH MEMBER Measures.ZyskProcentowy AS ([Measures].[Wartosc] - [Measures].[WartoscZakupu]) / [Measures].[WartoscZakupu], FORMAT_STRING = '0.000%' SELECT ZyskProcentowy ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] 6 Podstawy MDX Możliwe jest wyznaczenie członów wyliczanych Ad hoc przy zastosowaniu klauzuli WITH i odczytanie ich przez ADDCALCULATEDMEMBERS WITH MEMBER Measures.ZyskProcentowy AS '([Measures].[zysk]) / [Measures].[WartoscZakupu]', FORMAT_STRING = '#.00%' SELECT ADDCALCULATEDMEMBERS(MEASURES.MEMBERS) ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] Podstawy MDX WITH MEMBER Measures.ZyskProcentowy AS '([Measures].[zysk]) /[Measures].[WartoscZakupu]', FORMAT_STRING = '#.##%' MEMBER [Data Faktury].[Miesiac].PierwszaPolowa AS '[Miesiac].[1]+[Miesiac].[2]+[Miesiac].[3]+[Miesiac].[4]+[Miesiac].[5]+[Miesiac].[6]' MEMBER [Data Faktury].[Miesiac].DrugaPolowa AS '[Miesiac].[7]+[Miesiac].[8]+[Miesiac].[9]+[Miesiac].[10]+[Miesiac].[11] +[Miesiac].[12]' SELECT {PierwszaPolowa, DrugaPolowa, [Data Faktury].Miesiac.MEMBERS} ON COLUMNS, [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS on ROWS FROM [BiznesG] WHERE Measures.ZyskProcentowy Podstawy MDX WITH MEMBER Measures.ZyskProcentowy AS '([Measures].[zysk]) /[Measures].[WartoscZakupu]', FORMAT_STRING = '#.##%' MEMBER [Data Faktury].[Miesiac].PierwszaPolowa AS '[Miesiac].[1]+[Miesiac].[2]+[Miesiac].[3]+[Miesiac].[4]+[Miesiac].[5]+[Miesiac].[6]' MEMBER [Data Faktury].[Miesiac].DrugaPolowa AS '[Miesiac].[7]+[Miesiac].[8]+[Miesiac].[9]+[Miesiac].[10]+ [Miesiac].[11]+[Miesiac].[12]' SELECT {PierwszaPolowa, DrugaPolowa} ON columns, [KategoriaTowaruG].[Nazwa Kategorii].members on rows FROM [BiznesG] WHERE Measures.ZyskProcentowy Używając obliczanych członów możemy łatwo zdefiniować nowy wymiar CZASU służący do przedstawienia roku z rozbiciem na połowy : Podstawy MDX WITH MEMBER Measures.ZyskProcentowy AS '([Measures].[zysk]) /[Measures].[WartoscZakupu]', FORMAT_STRING = '#.##%‘, SOLVE_ORDER=1 MEMBER [Data Faktury].[Miesiac].PierwszaPolowa AS '[Miesiac].[1]+[Miesiac].[2]+[Miesiac].[3]+[Miesiac].[4]+[Miesiac].[5]+[Miesiac].[6]' MEMBER [Data Faktury].[Miesiac].DrugaPolowa AS '[Miesiac].[7]+[Miesiac].[8]+[Miesiac].[9]+[Miesiac].[10]+[Miesiac].[11] +[Miesiac].[12]' SELECT {PierwszaPolowa, DrugaPolowa, [Data Faktury].Miesiac.MEMBERS} ON COLUMNS, [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS on ROWS FROM [BiznesG] WHERE Measures.ZyskProcentowy Wymuszenie kolejność obliczania miar wyliczanych za pomocą SOLVE_ORDER=? 7 Podstawy MDX WITH MEMBER Measures.ZyskProcentowy AS '([Measures].[zysk]) /[Measures].[WartoscZakupu]', FORMAT_STRING = '#.##%', SOLVE_ORDER=1 MEMBER [Data Faktury].[Kwartal].PierwszaPolowa AS '[Kwartal].[1]+[Kwartal].[2]' MEMBER [Data Faktury].[Kwartal].DrugaPolowa AS '[Kwartal].[3]+[Kwartal].[4]' SELECT {PierwszaPolowa, DrugaPolowa,[Data Faktury].Kwartal.MEMBERS} ON COLUMNS, [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON ROWS FROM [BiznesG] WHERE Measures.ZyskProcentowy 1. How did Sales this period compare with Sales in the previous period? Qtr Mon Sales Q2 Delta 200 80 Apr 65 15 May 45 -20 Jun 90 45 (DELTA) = (Time.CurrentMember, Measures.Sales) - Podobna realizacja ale dla wprowadzonej hierarchii Kwartal (Time.CurrentMember.PrevMember, Measures.Sales) Porównanie z poprzednim okresem Year Qtr Mon 2000 Porównanie z równoległym okresem poprzedniego roku Sales 790 Q1 120 Jan 30 Feb 40 Mar Q2 Year Jan Feb Mar 50 Apr 65 May 45 Jun Jul 55 Aug 60 Sep 70 Q4 Q4 Oct Nov Dec 90 185 285 Oct 80 Nov 100 Dec 105 Mon Q1 200 Q3 Qtr 2000 2001 Q1 Jan Feb Mar Q4 Oct Nov Dec Sales 790 120 30 40 50 285 80 100 105 850 170 50 55 65 275 90 100 85 8 Porównanie z równoległym okresem poprzedniego roku 3. What have Sales been since the beginning of the year? Year Qtr Mon 2000 Sales Delta Jan Feb Mar 790 120 30 40 50 Jan 850 170 50 Feb Mar 55 65 Q1 2001 Q1 Year Mon Sales 20 (DELTA)= (Time.CurrentMember.Lag(12), Measures.Sales) (ParallelPeriod(Year,1,Time.CurrentMember), Measures.Sales) YTD 790 Q1 (Time.CurrentMember, Measures.Sales)- Źle Qtr 2000 120 120 Jan 30 30 Feb 40 70 Mar 50 120 + + Time.Jan,Measures.Sales Time.Feb,Measures.Sales Sum(YTD(Time.CurrentMember), Sales) Time.Mar,Measures.Sales Źle Wyznaczanie sumy bieżącej od początku roku Year Qtr Mon 2000 Q1 Jan Feb Mar Q2 Apr May Jun Q3 Jul Aug Sep Q4 Oct Nov Dec 3. What have Sales been since the beginning of the year? Sales 790 120 30 40 50 200 65 45 90 185 55 60 70 285 80 100 105 Year Qtr Mon Sales 2000 YTD 790 Q1 120 120 Jan 30 30 Feb 40 70 Mar 50 120 + + Time.Mar,Measures.Sales = Time.Jan,Measures.Sales Time.Feb,Measures.Sales Sum(YTD(Time.CurrentMember), Sales) 9 Podstawy MDX możemy wyświetlić zysk dla każdej kategorii towaru w każdym pierwszym kwartale (pierwszy potomek hierarchii) każdego roku: WITH SET [Kwartal1] AS GENERATE([Data Faktury].[DataFakturyH].[Rok].MEMBERS, {[Data Faktury].[DataFakturyH].CURRENTMEMBER.FIRSTCHILD}) SELECT [Kwartal1] ON COLUMNS, [Towar G].[Nazwa Kategorii].MEMBERS ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) Podstawy MDX możemy wyświetlić zysk dla każdej kategorii towaru w każdym ostatnim kwartale (Ostatni potomek hierarchii – o ile istnieje) każdego roku: WITH SET [Kwartal1] AS GENERATE([Data Faktury].[DataFakturyH].[Rok].MEMBERS, {[Data Faktury].[DataFakturyH].CURRENTMEMBER.LASTCHILD}) SELECT [Kwartal1] ON COLUMNS, [Towar G].[Nazwa Kategorii].MEMBERS ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) Podstawy MDX możemy wyświetlić zysk dla każdej kategorii towaru w każdym pierwszym kwartale (pierwszy potomek hierarchii - numeracja od 0) każdego roku: WITH SET [Kwartal1] AS GENERATE([Data Faktury].[DataFakturyH].[Rok].MEMBERS, {[Data Faktury].[DataFakturyH].CURRENTMEMBER.children(0)}) SELECT [Kwartal1] ON COLUMNS, [Towar G].[Nazwa Kategorii].MEMBERS ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) Podstawy MDX możemy wyświetlić zysk dla każdej kategorii towaru w każdym pierwszym kwartale (czwarty potomek hierarchii - numeracja od 0) każdego roku: WITH SET [Kwartal1] AS GENERATE([Data Faktury].[DataFakturyH].[Rok].MEMBERS, {[Data Faktury].[DataFakturyH].CURRENTMEMBER.children(3)}) SELECT [Kwartal1] ON COLUMNS, [Towar G].[Nazwa Kategorii].MEMBERS ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) Gdy niezdefiniowano dla któregoś roku nie jest wyświetlany 10 Podstawy MDX Wyznaczmy sprzedaż danej marki produktu jako udział procentowy w sprzedaży jego kategorii – czyli atrybutu, w odniesieniu do jego rodzica. Wyrażenie tworzące taki miarę obliczaną może zostać uzyskane przy użyciu właściwości CURRENTMEMBER oraz PARENT. WITH MEMBER MEASURES.ZyskKategorii AS ([KategoriaProduktuH].CURRENTMEMBER.PARENt, [Measures].[Zysk]) MEMBER MEASURES.ZyskProcentowy AS ([KategoriaProduktuH].CURRENTMEMBER, [Measures].[Zysk])/ ([KategoriaProduktuH].CURRENTMEMBER.PARENT, [Measures].[Zysk]), FORMAT_STRING = '0.00%' SELECT {Measures.ZyskKategorii, [Measures].[Zysk], MEASURES.ZyskProcentowy} ON COLUMNS, [KategoriaProduktuH].[Nazwa Towaru] ON ROWS FROM [BiznesG] Podstawy MDX PARENT może być używane wielokrotnie. W naszym przypadku przeniesie nas już na poziom ALL WITH MEMBER MEASURES.ZyskKategorii AS ([KategoriaProduktuH].CURRENTMEMBER.PARENT. PARENT, [Measures].[Zysk]) MEMBER MEASURES.ZyskProcentowy AS ([KategoriaProduktuH].CURRENTMEMBER, [Measures].[Zysk])/ ([KategoriaProduktuH].CURRENTMEMBER.PARENT.PARENT, [Measures].[Zysk]), FORMAT_STRING = '0.00%' SELECT {Measures.ZyskKategorii, [Measures].[Zysk], MEASURES.ZyskProcentowy} ON COLUMNS, [KategoriaProduktuH].[Nazwa Towaru] ON ROWS FROM [BiznesG] Podstawy MDX Wielokrotne użycie funkcji PARENT może być zastąpione przez obliczenie odpowiednich przodków członu CURRENTMEMBER przez funkcje ANCESTOR, zwracającą przodka na odpowiednim poziomie dla podanego członu. Konieczne jest użycie nazwy hierarchii: WITH MEMBER MEASURES.ZyskKategorii AS (ANCESTOR([KategoriaProduktuH].CURRENTMEMBER, [KategoriaProduktuH].[Nazwa Kategorii]), [Measures].[Zysk]) MEMBER MEASURES.ZyskProcentowy AS ([KategoriaProduktuH].currentmember, [Measures].[Zysk])/ (ANCESTOR([KategoriaProduktuH].CURRENTMEMBER, [KategoriaProduktuH].[Nazwa Kategorii]), [Measures].[Zysk]), FORMAT_STRING = '0.00%' SELECT {MEASURES.ZyskKategorii,[Measures].[Zysk], MEASURES.ZyskProcentowy} ON COLUMNS, [KategoriaProduktuH].[nazwa towaru] ON ROWS FROM [BiznesG] Podstawy MDX użycie nazwanych zbiorów i funkcji EXCEPT (odnajduje różnice pomiędzy dwoma zbiorami) umożliwia skonstruowanie wyrażenia, które pokaże procentową sprzedaż dla każdej grupy towarów w porównaniu do całości pomniejszonej o sprzedaż zegarów WITH SET [OproczZegarow] AS EXCEPT([KategoriaProduktuH].[Nazwa Kategorii].MEMBERS, [Towar G].[KategoriaProduktuH].[Nazwa Kategorii].[Clocks]) MEMBER Measures.ProcentSprzedazy AS ([KategoriaProduktuH].CURRENTMEMBER, [Measures].[Zysk]) / SUM([OproczZegarow], [Measures].[Zysk]), FORMAT_STRING = '#.00%' SELECT {[Measures].[Zysk], Measures.ProcentSprzedazy} ON COLUMNS, [OproczZegarow] ON ROWS FROM [BiznesG] 11 Formatowanie warunkowe WITH SET Towary as [KategoriaProduktuH].[Nazwa Kategorii].MEMBERS MEMBER Measures.zakup AS [Measures].[Wartosc] , FORMAT_STRING = IIF(zakup>800,'#.00','{#.00)'), fore_color = IIF(zakup>800,RGB(255,0,0), RGB(255,255,0)), back_color = IIF(zakup>800,RGB(0,255,255), RGB(0,155,0)), FONT_FLAGS = IIF(zakup>800,MDFF_BOLD or MDFF_UNDERLINE ,MDFF_ITALIC or MDFF_STRIKEOUT), FONT_NAME = IIF(zakup>800,ARIAL,Times), FONT_SIZE = IIF(zakup>800,16,10) SELECT Towary ON COLUMNS, [LokalizacjaKlientaH].[Województwo].MEMBERS ON ROWS FROM [BiznesG] Nie wszystko działa ?!! WHERE Measures.Zakup CELL PROPERTIES VALUE, FORMATTED_VALUE, CELL_ORDINAL, FORMAT_STRING, FORE_COLOR, BACK_COLOR, FONT_FLAGS, FONT_NAME, FONT_SIZE Podstawy MDX Rozpatrzmy zapytanie mające zwracać na osi kolumn informacje o sprzedaży w każdym roku oraz odpowiadające im szczegóły kwartalne. SELECT GENERATE([DataFakturyH].[Rok].MEMBERS, {[DataFakturyH].CURRENTMEMBER, [DataFakturyH].CURRENTMEMBER.CHILDREN}) ON COLUMNS, [KategoriaProduktuH].[Nazwa Kategorii].members ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) Podstawy MDX To samo ale z zastosowaniem DESCENDANTS SELECT GENERATE([DataFakturyH].[Rok].MEMBERS, {[DataFakturyH].CURRENTMEMBER, DESCENDANTS([DataFakturyH].CURRENTMEMBER, [Data Faktury].[DataFakturyH].[Kwartal])}) ON COLUMNS, [KategoriaProduktuH].[Nazwa Kategorii].members ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) Podstawy MDX To samo ale z rozbiciem na miesiące SELECT GENERATE([DataFakturyH].[Rok].MEMBERS, {[DataFakturyH].CURRENTMEMBER, DESCENDANTS([DataFakturyH].CURRENTMEMBER, [Data Faktury].[DataFakturyH].[Miesiac])}) ON COLUMNS, [KategoriaProduktuH].[Nazwa Kategorii].members ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) 12 Podstawy MDX Pokazanie wzrostu w okresie czasu umożliwia funkcja PREVMEMBER. Jeżeli mielibyśmy wyświetlić zysk ze sprzedaży i przyrostową zmianę od poprzedniego członu czasu na poziomie kolejnych miesięcy WITH MEMBER Measures.[wzrost Zysku] AS ([Measures].[Zysk]) - ([Measures].[Zysk],[DataFakturyH].PREVMEMBER), FORMAT_STRING = '###,###.00 ZŁ' SELECT {[Measures].[Zysk], Measures.[wzrost Zysku]} ON COLUMNS, {DESCENDANTS([DataFakturyH], [DataFakturyH].[miesiac])} ON ROWS FROM [BiznesG] Podstawy MDX Użycie NEXTMEMBER w tym wyrażeniu pokazałoby sprzedaż dla każdego miesiąca zestawioną ze sprzedażami z poprzednich miesięcy. WITH MEMBER Measures.[wzrost Zysku] AS ([Measures].[Zysk]) - ([Measures].[Zysk],[DataFakturyH]. NEXTMEMBER), FORMAT_STRING = '###,###.00 ZŁ' SELECT {[Measures].[Zysk], Measures.[wzrost Zysku]} ON COLUMNS, {DESCENDANTS([DataFakturyH], [DataFakturyH].[miesiac])} ON ROWS FROM [BiznesG] Podstawy MDX Możemy również użyć funkcji LEAD, która zwraca człon oddalony w wymiarze o określoną liczbę pozycji od wskazanego członu. WITH MEMBER Measures.[wzrost Zysku] AS ([Measures].[Zysk]) - ([Measures].[Zysk],[DataFakturyH]. LEAD)(-2)), FORMAT_STRING = '###,###.00 ZŁ' SELECT {[Measures].[Zysk], Measures.[wzrost Zysku]} ON COLUMNS, {DESCENDANTS([DataFakturyH], [DataFakturyH].[miesiac])} ON ROWS FROM [BiznesG] Podstawy MDX PARALLELPERIOD pozwala na łatwe porównanie wzrostu ze wzrostem z tego samego przedziału czasu w poprzednim kwartale: WITH MEMBER Measures.[wzrost Zysku] AS ([Measures].[Zysk]) - (Measures.[Zysk], PARALLELPERIOD([DataFakturyH].[Kwartal])), FORMAT_STRING = '###,###.00 ZŁ' SELECT {[Measures].[Zysk], Measures.[wzrost Zysku]} ON COLUMNS, {DESCENDANTS([DataFakturyH], [DataFakturyH].[miesiac])} ON ROWS FROM [BiznesG] Pojawiają się błędy gdy nie zdefiniowno „równoległego” miesiąca. Miesiące w obrębie kwartału są wykrywane jako kolejne wystąpienia na liście, niezgodnie z kalendarzem 13 Podstawy MDX Można sprawdzić o ile wzrosła sprzedaż po pierwszym miesiącu sezonu. Używając kwartału do przedstawienia sezonu, można mierzyć różnicę w sprzedaży jednostek dla każdego miesiąca, porównując z miesiącem otwierającym kwartał: WITH MEMBER Measures.[wzrost Zysku] AS ([Measures].[Zysk]) - (Measures.[Zysk], OPENINGPERIOD([DataFakturyH].Miesiac, [DataFakturyH].CURRENTMEMBER.PARENT)), FORMAT_STRING = '###,###.00 ZŁ' SELECT {[Measures].[Zysk], Measures.[wzrost Zysku]} ON COLUMNS, {DESCENDANTS([DataFakturyH], [DataFakturyH].[miesiac])} ON ROWS FROM [BiznesG] OPENINGPERIOD(poziom, człon) CLOSINGINGPERIOD(poziom, człon) Podstawy MDX Przy użyciu funkcji SUM i PERIODSTODATE można zdefiniować obliczany człon, który wyświetli informację year-to-date.. Miarą jest suma bieżąca na poziomie roku: PERIODSTODATE([Time].[Year], [Time].CURRENTMEMBER) WITH MEMBER Measures.Zysk_YTD AS SUM(PERIODSTODATE([DataFakturyH].[Rok],[DataFakturyH].CURRENTMEMBER), [Measures].[Zysk]), FORMAT_STRING = '#.00' SELECT {[KategoriaTowaruG].[Nazwa Kategorii].MEMBERS} ON Columns, {DESCENDANTS([DataFakturyH], [DataFakturyH].miesiac)} ON rows FROM [BiznesG] WHERE (Measures.Zysk_YTD) Podstawy MDX W postaci skróconej można zastosować funkcję YTD() WITH MEMBER Measures.Zysk_YTD AS SUM(YTD(), [Measures].[Zysk]), FORMAT_STRING = '#.00' SELECT {[KategoriaTowaruG].[Nazwa Kategorii].MEMBERS} ON Columns, {DESCENDANTS([DataFakturyH], [DataFakturyH].Miesiac)} ON rows FROM [BiznesG] WHERE (Measures.Zysk_YTD) Oprócz YTD() istnieją QTD(), MTD() i WTD(). Podstawy MDX Przy użyciu funkcji SUM i PERIODSTODATE można zdefiniować obliczany człon, który wyświetli informację Quarter-to-date.. Miarą jest suma bieżąca na poziomie Kwartału: WITH MEMBER Measures.Zysk_QTD AS SUM(PERIODSTODATE([DataFakturyH].[Kwartal],[DataFakturyH].CURRENTMEMB ER), [Measures].[Zysk]), FORMAT_STRING = '#.00' SELECT {[KategoriaTowaruG].[Nazwa Kategorii].MEMBERS} ON Columns, {DESCENDANTS([DataFakturyH], [DataFakturyH].miesiac)} ON rows FROM [BiznesG] WHERE (Measures.Zysk_QTD) 14 Podstawy MDX To samo przy użyciu funkcji QTD: WITH MEMBER Measures.Zysk_QTD AS SUM(QTD(), [Measures].[Zysk]), FORMAT_STRING = '#.00' SELECT {[KategoriaTowaruG].[Nazwa Kategorii].MEMBERS} ON Columns, [DataFakturyH].miesiac ON rows FROM [BiznesG] WHERE (Measures.Zysk_QTD) Podstawy MDX Usuwanie pustych członów z osi możemy osiągnąć przez zastosowanie klauzuli NON EMPTY, SELECT [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON COLUMNS, NON EMPTY{CROSSJOIN( [Klienci G].[Województwo].MEMBERS, [Data Faktury].[Kwartal].MEMBERS)} ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) Przy takiej definicji krotki zapytanie bieżące i z poprzedniej strony zwracają to samo Podstawy MDX W wielu przypadkach kombinacja członów z różnych wymiarów jest zamknięta w nawiasach. Kombinacja taka znana jest jako krotka (tuplet) i jest wykorzystywana do wyświetlenia wielu wymiarów na jednej osi. SELECT [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON COLUMNS, {CROSSJOIN( [Klienci G].[Województwo].MEMBERS, [Data Faktury].[Kwartal].MEMBERS)} ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) Podstawy MDX Do filtrowania bardziej szczegółowego, MDX udostępnia funkcję FILTER. Zwraca ona zbiór, który jest wynikiem filtrowania na podstawie określonego warunku. FILTER (zbiór, warunek_wyszukiwania) SELECT [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON COLUMNS, FILTER({[LokalizacjaKlientaH].[Miasto].MEMBERS}, ([Measures].[Zysk], [DataFakturyH].[All])>500) ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk]) 15 Podstawy MDX Do filtrowania bardziej szczegółowego, MDX udostępnia funkcję FILTER. Zwraca ona zbiór, który jest wynikiem filtrowania na podstawie określonego warunku. FILTER (zbiór, warunek_wyszukiwania) SELECT [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON COLUMNS, FILTER({[LokalizacjaKlientaH].[Miasto].MEMBERS}, ([Measures].[Zysk], [DataFakturyH].[All])>500) ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk], [DataFakturyH].[Rok].[2003]) Podstawy MDX Zysk których z produktów spada poniżej średniej dla województwa ????? WITH MEMBER [Measures].[ZyskProcentowy] AS ([Measures].[Wartosc]-[Measures].[WartoscZakupu]) / ([Measures].[WartoscZakupu]), FORMAT_STRING = '#.00%' SELECT NON EMPTY {[KategoriaTowaruG].[Nazwa Kategorii].MEMBERS} ON COLUMNS, FILTER({[LokalizacjaKlientaH].[Miasto].MEMBERS}, ([Measures].[ZyskProcentowy], [DataFakturyH].[All]) < ([Measures].[ZyskProcentowy], [DataFakturyH].[All], ANCESTOR([LokalizacjaKlientaH].CURRENTMEMBER, [LokalizacjaKlientaH].[Województwo]))) ON ROWS FROM [BiznesG] WHERE ([Measures].[ZyskProcentowy], [DataFakturyH].[All]) Filtr dla zysku we wszystkich latach większego niż 500 ale wyświetlono zysk z roku 2003 Podstawy MDX Jest sens stosowanie NON EMPTY – wyeliminowano PABIANICE SELECT [KategoriaTowaruG].[Nazwa Kategorii].MEMBERS ON COLUMNS, NON EMPTY(FILTER({[LokalizacjaKlientaH].[Miasto].MEMBERS}, ([Measures].[Zysk], [DataFakturyH].[All])>500)) ON ROWS FROM [BiznesG] WHERE ([Measures].[Zysk], [DataFakturyH].[Rok].[2003]) Podstawy MDX Rozpatrzmy proste zapytanie o miary dla lokalizacji klientów (miasta): SELECT [Measures].MEMBERS ON COLUMNS, [LokalizacjaKlientaH].[Miasto].MEMBERS ON ROWS FROM [BiznesG] Filtr dla zysku we wszystkich latach większego niż 500 ale wyświetlono zysk z roku 2003 16 Podstawy MDX Podstawy MDX Sortowanie wyników Pierwszym wyświetlonym miastem jest Bydgoszcz etc... Naturalna kolejność nie jest zbyt widoczna ponieważ nie znamy członu z poziomu rodzica. Jeśli bylibyśmy zainteresowani miastami wylistowanymi między Kutno a Czersk musielibyśmy napisać: SELECT [Measures].MEMBERS ON COLUMNS, [LokalizacjaKlientaH].[Miasto].[KUTNO]:[CZERSK] ON ROWS FROM [BiznesG] Podstawy MDX Sortowanie wyników ORDER(zbiór, wyrażenie [, ASC | DESC | BASC | BDESC]) Prefiks “B” wskazuje, że hierarchiczny porządek może zostać rozbity. SELECT [Measures].MEMBERS ON COLUMNS, ORDER([LokalizacjaKlientaH].[Miasto].[KUTNO]:[CZERSK], [LokalizacjaKlientaH].CURRENTMEMBER.NAME, BASC) ON ROWS FROM [BiznesG] ORDER(zbiór, wyrażenie [, ASC | DESC | BASC | BDESC]) Brak prefiksu “B” wskazuje, że hierarchiczny porządek nie może zostać rozbity. SELECT [Measures].MEMBERS ON COLUMNS, ORDER([LokalizacjaKlientaH].[Miasto].[KUTNO]:[CZERSK], [LokalizacjaKlientaH].CURRENTMEMBER.NAME, ASC) ON ROWS FROM [BiznesG] Podstawy MDX Dość często bieżące sortowanie jest oparte o aktualną miarę. Zapytamy o informacje sprzedaży w miastach, uporządkowaną według efektywności sprzedaży: SELECT [Measures].MEMBERS ON COLUMNS, ORDER([LokalizacjaKlientaH].[Miasto].MEMBERS, [Measures].[Wartosc], DESC) ON ROWS FROM [BiznesG] W przykładzie tym sortowanie odbyło się po właściwości Name. Zwraca on nazwę poziomu, wymiaru, członu, lub hierarchii. Istnieje podobna właściwość – UniqueName zwracająca odpowiednią unikalną nazwę. 17 Podstawy MDX Dość często bieżące sortowanie jest oparte o aktualną miarę. Zapytamy o informacje sprzedaży w miastach, uporządkowaną według efektywności sprzedaży: SELECT [Measures].MEMBERS ON COLUMNS, ORDER([LokalizacjaKlientaH].[Miasto].MEMBERS, [Measures].[Wartosc], BDESC) ON ROWS FROM [BiznesG] Podstawy MDX TOPCOUNT zwraca ze zbioru n najlepszych na podstawie podanego wyrażenia wyników. TOPCOUNT(zbiór, n, wyrażenie_numeryczne) Poprzednie wyrażenie możemy zatem przepisać: SELECT [Measures].MEMBERS ON COLUMNS, TOPCOUNT([LokalizacjaKlientaH].[Miasto].MEMBERS, 10, [Measures].[Wartosc]) ON ROWS FROM [BiznesG] Bez rozbicia wynikającego z hierarchii Podstawy MDX HEAD funkcja zwracająca pierwszych n członów z podanego zbioru. Podobnie TAIL – zwraca n ostatnich członów z podanego zbioru. Ograniczmy zakres wyświetlanych miast do 10 najbardziej wydajnych: SELECT [Measures].MEMBERS ON COLUMNS, HEAD(ORDER([LokalizacjaKlientaH].[Miasto].MEMBERS, [Measures].[Wartosc], BDESC), 10) ON ROWS FROM [BiznesG] Podstawy MDX Zapytanie MDX, które wyświetla górne 10 miast, w oparciu o ilość transakcji sprzedaży, oraz jak dużo sprzedały łącznie pozostałe miasta. Takie wyrażenie pokaże także inne zastosowanie funkcji SUM, nawiązujące do nazwanych zbiorów i obliczanych członów: WITH SET TopTens AS TOPCOUNT([LokalizacjaKlientaH].[Miasto].MEMBERS, 10, [Measures].[Ilosc]) MEMBER [LokalizacjaKlientaH].[Inne Miasta] AS ([LokalizacjaKlientaH].[All], Measures.CURRENTMEMBER) SUM(TopTens, Measures.CURRENTMEMBER) SELECT [Measures].MEMBERS ON COLUMNS, {TopTens, [Inne Miasta]} ON ROWS FROM [BiznesG] Istnieje również TOPPERCENT, TOPSUM Oczywiście istnieje seria funkcji BOTTOM 18 Podstawy MDX Wyświetlanie listy miast, których ilość transakcji sprzedaży obejmuje 50% całości sprzedaży: SELECT [Measures].MEMBERS ON COLUMNS, TOPPERCENT({[Klienci G].[LokalizacjaKlientaH].[Miasto].MEMBERS}, 50, [Measures].[Ilosc]) ON ROWS FROM [BiznesG] Podstawy MDX rozkład ilości sprzedaży dla typów sklepów: SELECT [Nazwa Kategorii].MEMBERS ON COLUMNS, TOPPERCENT({[LokalizacjaKlientaH].[Miasto].MEMBERS}, 50, [Measures].[Ilosc]) ON ROWS FROM [BiznesG] WHERE [Measures].[Ilosc] Podstawy MDX Wyświetlanie listy 50% osób, których zarobki w roku 2004 były najwyższe SELECT TOPPERCENT ([Osoby G].[Pracownik].[Pracownik].members, 50, ([Measures].[Brutto], [Data Zarobki].[Rok].[2004])) ON ROWS, {[Data Zarobki].[Rok].[2004]} ON COLUMNS FROM ZarobkiG Podstawy MDX Zastosowanie TOPSUM WITH MEMBER [Data Faktury].[Rok].[2002 + 2003] AS ([Measures].[Wartosc], [Data Faktury].[Rok].[2002]) + ([Measures].[Wartosc], [Data Faktury].[Rok].[2003]) SELECT {[Data Faktury].[Rok].[2002], [Data Faktury].[Rok].[2003] , [Data Faktury].[Rok].[2002 + 2003]} ON COLUMNS, TOPSUM([Towar G].[Nazwa Towaru].[Nazwa Towaru].members, 10000, [Data Faktury].[Rok].[2002 + 2003]) ON ROWS FROM BiznesG WHERE [Measures].[Wartosc] 19 Podstawy MDX Funkcje statystyczne AVG, MEDIAN, MAX, MIN, VAR oraz STDDEV. Format jest jednakowy dla wszystkich: FUNKCJA(zbiór, wyrażenie_numeryczne) WITH MEMBER [DataFakturyH].[SredniaSprzedaz] AS AVG(DESCENDANTS([DataFakturyH].[Rok], [DataFakturyH].[Miesiac])) MEMBER [DataFakturyH].[SredniaIlosc] AS COUNT(DESCENDANTS([DataFakturyH].[Rok], [DataFakturyH].[Miesiac]),EXCLUDEEMPTY) SELECT {[DataFakturyH].[Rok],[SredniaSprzedaz],[SredniaIlosc]} ON COLUMNS, [KategoriaTowaruG].[Nazwa Kategorii] ON ROWS FROM [BiznesG] WHERE [Measures].[Ilosc] Podstawy MDX Funkcje te, zwane “user-defined functions” (UDF) mogą przyjmować argumenty i zwracać wartości w składni MDX. UDF mogą być tworzone w dowolnym języku wspomagającym COM (Common Object Model), Na dodatek, MDX obsługuje wiele funkcji z biblioteki Microsoft Visual Basic for Applications (VBA) Expression Services. Biblioteka ta jest dołączona do OLAP Services i jest automatycznie rejestrowana. Możemy zapytać o miary dla miasta, gdzie wartość zawiera łańcuch “KA”: SELECT Measures.MEMBERS ON COLUMNS, FILTER({[LokalizacjaKlientaH].[Miasto].MEMBERS}, VBA!INSTR(1, [Miasto].CURRENTMEMBER.Name, "KA")>0) ON ROWS FROM [BiznesG] Podstawy MDX Jeśli zapytanie ma zwracać wzrost procentowy WITH MEMBER Measures.[WzrostZysku] AS ([Measures].[Zysk]) / ([Measures].[Zysk], [DataFakturyH].PREVMEMBER), FORMAT_STRING = '#.00%' SELECT {[Measures].[Zysk], [WzrostZysku] } ON COLUMNS, DESCENDANTS([DataFakturyH].[Rok], [DataFakturyH].[Miesiac]) ON ROWS FROM [BiznesG] Problemem - pierwszy okres czasu powoduje dzielenie przez zero... Podstawy MDX Ten problem może zostać w omnięty przez użycie IIF i sprawdzenie istnienia pustej komórki: WITH MEMBER Measures.[WzrostZysku] AS IIF( ISEMPTY([DataFakturyH].PREVMEMBER), 1, ([Measures].[Zysk]) / ([Measures].[Zysk], [DataFakturyH].PREVMEMBER)), FORMAT_STRING = '#.00%' SELECT {[Measures].[Zysk], [WzrostZysku] } ON COLUMNS, DESCENDANTS([DataFakturyH].[Rok], [DataFakturyH].[Miesiac]) ON ROWS FROM [BiznesG] Prefiks VBA nie jest potrzebny. Wskazuje jedynie pełnokwalifikowane pochodzenie funkcji. 20 Podstawy MDX Taka sama funkcjonalność może być osiągnięta przy użyciu funkcji COALESCEEMPTY, która przypisuje pustej wartości komórki liczbę lub łańcuch i go zwraca. W tym przypadku, pusta komórka z poprzedniego członu czasu, byłaby zastąpiona wartością bieżącym członem czasu: WITH MEMBER Measures.[WzrostZysku] AS ([Measures].[Zysk]) / COALESCEEMPTY(([Measures].[Zysk], [DataFakturyH].PREVMEMBER),[Measures].[Zysk]), FORMAT_STRING = '#.00%' SELECT {[Measures].[Zysk], [WzrostZysku] } ON COLUMNS, DESCENDANTS([DataFakturyH].[Rok], [DataFakturyH].[Miesiac]) ON ROWS FROM [BiznesG] Średnia dla miast dla wybranych województw za lata 2001 do 2004 WITH MEMBER [Measures].[lubelskie AVG] AS AVG({[Klienci G].[lubelskie].CHILDREN},[Measures].[Wartosc]) MEMBER [Measures].[łódzkie AVG] AS AVG({[Klienci G].[łódzkie].CHILDREN},[Measures].[Wartosc]) MEMBER [Measures].[pomorskie AVG] AS AVG({[Klienci G].[pomorskie].CHILDREN},[Measures].[Wartosc]) SELECT {([Measures].[lubelskie AVG]), ([Measures].[łódzkie AVG]), ([Measures].[pomorskie AVG])} ON COLUMNS, {([Data Faktury].[2001]:[2003])} ON ROWS FROM BiznesG Średnia bieżąca - CENTRALNA WITH MEMBER Measures.SredniaBiezaca AS AVG({[Miesiac].CURRENTMEMBER, [Miesiac].PREVMEMBER, [Miesiac].NEXTMEMBER},[Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' SELECT [KategoriaProduktuH].[Nazwa Kategorii].[THAN] ON COLUMNS, [DataFakturyH].[Miesiac].MEMBERS ON ROWS FROM [BiznesG] WHERE Measures.SredniaBiezaca Średnia bieżąca - WSTECZNA WITH MEMBER Measures.SredniaBiezaca AS AVG({[Miesiac].CURRENTMEMBER, [Miesiac].PREVMEMBER, [Miesiac].PREVMEMBER.PREVMEMBER},[Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' SELECT [KategoriaProduktuH].[Nazwa Kategorii].[THAN] ON COLUMNS, [DataFakturyH].[Miesiac].MEMBERS ON ROWS FROM [BiznesG] WHERE Measures.SredniaBiezaca 21 Średnia bieżąca – WSTECZNA Inna realizacja WITH MEMBER Measures.SredniaBiezaca AS AVG({[Miesiac].CURRENTMEMBER.LAG(2):[Miesiac].CURRENTMEMBER}, [Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' SELECT [KategoriaProduktuH].[Nazwa Kategorii].[THAN] ON COLUMNS, [DataFakturyH].[Miesiac].MEMBERS ON ROWS FROM [BiznesG] WHERE Measures.SredniaBiezaca Średnia bieżąca - PORÓWNANIE WITH MEMBER Measures.SredniaBiez AS AVG({[Miesiac].CURRENTMEMBER.LAG(2):[Miesiac].CURRENTMEMBER}, [Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' MEMBER Measures.SredniaBiezaca AS AVG({[Miesiac].CURRENTMEMBER.LAG(5):[Miesiac].CURRENTMEMBER}, [Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' SELECT {Wartosc, Measures.SredniaBiez, Measures.SredniaBiezaca} ON COLUMNS, [Data Faktury].[DataFakturyH].[Miesiac].MEMBERS ON ROWS FROM [BiznesG] WHERE {[KategoriaProduktuH].[Nazwa Kategorii].[THAN]}; 1 800,00 z? 1 600,00 z? 1 400,00 z? 1 200,00 z? Wartosc SredniaBiez SredniaBiezaca 1 000,00 z? 800,00 z? 600,00 z? 400,00 z? 200,00 z? Średnia bieżąca - PORÓWNANIE 1 800,00 z? 1 600,00 z? 1 600,00 z? 31 33 35 25 27 29 19 21 23 13 15 17 1 400,00 z? 1 200,00 z? 600,00 z? 400,00 z? 400,00 z? 200,00 z? 200,00 z? 35 33 31 29 27 25 23 21 19 17 15 13 9 7 31 33 35 25 27 29 19 21 23 13 15 17 7 9 11 3 z? 1 - 5 SredniaBiez SredniaBiezaca 800,00 z? 600,00 z? z? Wartosc 1 000,00 z? 11 800,00 z? 5 Wartosc SredniaBiez SredniaBiezaca 1 000,00 z? 3 1 200,00 z? 1 7 WITH MEMBER Measures.SredniaBiez AS AVG({[Miesiac].CURRENTMEMBER.LAG(-2):[Miesiac].CURRENTMEMBER}, [Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' MEMBER Measures.SredniaBiezaca AS AVG({[Miesiac].CURRENTMEMBER.LAG(2):[Miesiac].CURRENTMEMBER}, [Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' SELECT {Wartosc, Measures.SredniaBiez, Measures.SredniaBiezaca} ON COLUMNS, [Data Faktury].[DataFakturyH].[Miesiac].MEMBERS ON ROWS FROM [BiznesG] WHERE {[KategoriaProduktuH].[Nazwa Kategorii].[THAN]}; 1 800,00 z? - 9 Średnia bieżąca - PORÓWNANIE WITH MEMBER Measures.SredniaBiez AS AVG({[Miesiac].CURRENTMEMBER.LAG(2):[Miesiac].CURRENTMEMBER}, [Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' MEMBER Measures.SredniaBiezaca AS Avg({[Miesiac].CURRENTMEMBER,[Miesiac].PREVMEMBER, [Miesiac].NEXTMEMBER}, [Measures].[Wartosc]), FORMAT_STRING = '#.00 zł' SELECT {Wartosc, Measures.SredniaBiez, Measures.SredniaBiezaca} ON COLUMNS, [Data Faktury].[DataFakturyH].[Miesiac].MEMBERS ON ROWS FROM [BiznesG] WHERE {[KategoriaProduktuH].[Nazwa Kategorii].[THAN]}; 1 400,00 z? 11 1 3 z? 5 - 22 Podstawy MDX CROSS JOIN na wymiarach definiowanych ad hoc LITERATURA •http://msdn.microsoft.com/library/en-us/olapdmad/agmdxbasics_4erb.asp •http://msdn.microsoft.com/library/en-us/olapdmad/agmdxbasics_6wag.asp •http://msdn.microsoft.com/library/en-us/olapdmad/agmdxadvanced_5ke0.asp •http://msdn.microsoft.com/library/en-us/olapdmad/agmdxadvanced_0woo.asp •http://msdn.microsoft.com/library/en-us/olapdmad/agmdxfunctintro_65iw.asp WITH SET czasr AS [DataFakturyH].[Rok].members SET czasq AS [Data Faktury].[Kwartal].members SET czasm AS [Data Faktury].[Miesiac].members SELECT Measures.Wartosc ON COLUMNS , CROSSJOIN( CROSSJOIN(CZASR, FILTER(CZASQ, CZASQ.currentmember.value <> [Kwartal].[all]) ) ,FILTER(czasm, CZASm.currentmember.value <> [miesiac].[all])) ON ROWS FROM [BiznesG] CROSS JOIN na wymiarach definiowanych ad hoc CROSS JOIN na wymiarach definiowanych ad hoc WITH SET czasr AS [DataFakturyH].[Rok].members SET czasq AS [Data Faktury].[Kwartal].members SELECT Measures.Wartosc ON COLUMNS , CROSSJOIN(CZASR, FILTER(CZASQ, CZASQ.currentmember.value <> [Kwartal].[all]) ) ON ROWS FROM [BiznesG] WITH SET czasr AS [DataFakturyH].[Rok].members SET czasq AS [Data Faktury].[Kwartal].members SET czasm AS [Data Faktury].[Miesiac].members SET czasd AS [Data Faktury].[Dzien].members SELECT Measures.Wartosc ON COLUMNS , CROSSJOIN( CROSSJOIN( CROSSJOIN(CZASR, FILTER(CZASQ, CZASQ.currentmember.value <> [Kwartal].[all]) ) ,FILTER(czasm, CZASm.currentmember.value <> [miesiac].[all])), FILTER(czasd, CZASd.currentmember.value <> [dzien].[all])) ON ROWS FROM [BiznesG] 23 CROSS JOIN na wymiarach definiowanych ad hoc (strasznie wolne) WITH SET czasr AS [DataFakturyH].[Rok].members SET czasq AS [Data Faktury].[Kwartal].members SET czasm AS [Data Faktury].[Miesiac].members SET czasd AS [Data Faktury].[Dzien].members SET kategoria AS [KategoriaProduktuH].[Nazwa Kategorii].members SET towar AS [Towar G].[Nazwa Towaru].members SELECT nonempty(CROSSJOIN(kategoria, filter(towar,towar.currentmember.value<>[Nazwa Towaru].[all]))) ON columns , nonempty(CROSSJOIN( CROSSJOIN( CROSSJOIN(CZASR, FILTER(CZASQ, CZASQ.currentmember.value <> [Kwartal].[all]) ) ,FILTER(czasm, CZASm.currentmember.value <> [miesiac].[all])), FILTER(czasd, CZASd.currentmember.value <> [dzien].[all]))) ON rows FROM [BiznesG] where [Measures].[Wartosc] CROSS JOIN na wymiarach definiowanych ad hoc (inna realizacja) WITH SET czasr AS [DataFakturyH].[Rok].members SET czasq AS [Data Faktury].[Kwartal].members SET czasm AS [Data Faktury].[Miesiac].members SET czasd AS [Data Faktury].[Dzien].members SET kategoria AS [KategoriaProduktuH].[Nazwa Kategorii].members SET towar AS [Towar G].[Nazwa Towaru].members SET Towary AS nonempty(CROSSJOIN(kategoria, filter(towar,towar.currentmember.value<>[Nazwa Towaru].[all]))) SET CZAS AS nonempty( CROSSJOIN( CROSSJOIN( CROSSJOIN( CZASR, FILTER(CZASQ, CZASQ.currentmember.value <> [Kwartal].[all]) ) ,FILTER(czasm, CZASm.currentmember.value <> [miesiac].[all])), FILTER(czasd, CZASd.currentmember.value <> [dzien].[all]))) SELECT towary ON columns , czas on rows FROM [BiznesG] where [Measures].[Wartosc] Podstawy MDX Człony obliczane mogą być również zależne od członu istniejącego w tej samej hierarchii, tak jak w przykładzie: WITH MEMBER [Time].[1997].[H1] AS '[Time].[1997].[Q1] + [Time].[1997].[Q2]' MEMBER [Time].[1997].[H2] AS '[Time].[1997].[Q3] + [Time].[1997].[Q4]' SELECT {[Time].[1997].[H1], [Time].[1997].[H2]} ON COLUMNS, [Store].[Store Name].MEMBERS ON ROWS FROM [Sales] WHERE (Measures.Profit) Wzrost wynagrodzenia za okres od 2002 do 2004 WITH MEMBER [Measures].[Wzrost_wynag] As ([Data Zarobki].[Rok].Currentmember,[Measures].[Brutto])([Data Zarobki].[Rok].PrevMember, [Measures].[Brutto]) SELECT {([Measures].[Brutto]), ([Measures].[Wzrost_wynag])} ON COLUMNS, {[Data Zarobki].[Rok].[2002]:[Rok].[2004]} ON ROWS FROM ZarobkiG 24 Zestawy rekordów dwie realizacje tego samego SELECT {[Data Faktury].[DataFakturyH].[Rok].members} ON COLUMNS, {[Towar G].[LokalizacjaProducentaH].[Województwo].[pomorskie].CHILDREN, [Towar G].[LokalizacjaProducentaH].[Województwo].[śląskie].CHILDREN} ON ROWS FROM BiznesG WHERE [Measures].[Wartosc] SELECT {[Data Faktury].[DataFakturyH].[Rok].members} ON COLUMNS, {UNION( [Towar G].[LokalizacjaProducentaH].[Województwo].[pomorskie].CHILDREN, [Towar G].[LokalizacjaProducentaH].[Województwo].[śląskie].CHILDREN )} ON ROWS FROM BiznesG WHERE [Measures].[Wartosc] Podwójne filtrowanie i sortowanie wartość dla roku 2004 większa niż dla 2003 różnica wartości między 2003 a 2004 większa niż 50 WITH MEMBER [Data Faktury].[Rok].[2004 - 2003] AS ([Measures].[Wartosc], [Data Faktury].[Rok].[2004]) – ([Measures].[Wartosc], [Data Faktury].[Rok].[2003]) SELECT {([Data Faktury].[Rok].[2003]),([Data Faktury].[Rok].[2004]), ([Data Faktury].[Rok].[2004 - 2003])} ON COLUMNS, {ORDER(FILTER(FILTER([Towar G].[Nazwa Towaru].[Nazwa Towaru].members, ([Measures].[Wartosc], [Data Faktury].[Rok].[2004]) > ([Measures].[Wartosc], [Data Faktury].[Rok].[2003])), [Data Faktury].[Rok].[2004 - 2003] >50), [Data Faktury].[Rok].[2004 - 2003], DESC)} ON ROWS FROM BiznesG WHERE ([Measures].[Wartosc], [Klienci G].[Klienci G].[(All)], [Osoby G].[Osoby G].[(All)]) Definiowanie miar i zestawów ad hoc oraz ich wzajemne wykorzystanie WITH SET [10 najlepszych] AS TOPCOUNT([Klienci G].[Klient].[Klient].members,10, [Data Faktury].[Rok].[2001 + 2003]) MEMBER [Klienci G].[Klient].[Suma 10] AS SUM([10 najlepszych], [Measures].[Wartosc]) MEMBER [Data Faktury].[Rok].[2001 + 2003] AS ([Measures].[Wartosc], [Data Faktury].[Rok].[2001]) + ([Measures].[Wartosc], [Data Faktury].[Rok].[2002]) + ([Measures].[Wartosc], [Data Faktury].[Rok].[2003]) MEMBER [Klienci G].[Klient].[Udzial %] AS ([Klienci G].[Klient].[Suma 10], [Measures].[Wartosc])*100/([Klienci G].[Klient].[All], [Measures].[Wartosc]) SELECT {[Data Faktury].[Rok].[2001 + 2003]} ON COLUMNS, {[10 najlepszych],[Klienci G].[Klient].[Suma 10], [Klienci G].[Klient].[Udzial %]} ON ROWS FROM BiznesG Definiowanie miar i zestawów ad hoc oraz ich wzajemne wykorzystanie (minimalna notacja) WITH SET [10 najlepszych] AS TOPCOUNT([Klient].[Klient].members,10, [Rok].[2001 + 2003]) MEMBER [Klient].[Suma 10] AS SUM([10 najlepszych], [Wartosc]) MEMBER [Rok].[2001 + 2003] AS ([Wartosc], [Rok].[2001]) + ([Wartosc], [Rok].[2002]) + ([Wartosc], [Rok].[2003]) MEMBER [Klient].[Udzial %] AS ([Klient].[Suma 10], [Wartosc])*100/([Klient].[All], [Wartosc]) SELECT {[Data Faktury].[Rok].[2001 + 2003]} ON COLUMNS, {[10 najlepszych],[Klient].[Suma 10], [Klient].[Udzial %]}ON ROWS FROM BiznesG 25