ITA-102 Hurtownie Danych Moduł 8 Wersja 1.0 Spis treści Analityczny język zapytań MDX: zaawansowane Analityczny język zapytań MDX: zaawansowane... 1 Informacje o module... 2 Przygotowanie teoretyczne... 4 Podstawy teoretyczne... 4 Porady praktyczne... 5 Uwagi dla studenta... 5 Dodatkowe źródła informacji... 6 Laboratorium podstawowe... 7 Laboratorium rozszerzone... 16 Zadanie 1 (czas wykonania 10 min)... 16 Zadanie 2 (czas wykonania 10 min)... 16 Zadanie 3 (czas wykonania 12 min)... 16 Zadanie 4 (czas wykonania 12 min)... 16 Zadanie 5 (czas wykonania 15 min)... 16 Zadanie 6 (czas wykonania 15 min)... 16 Zadanie 7 (czas wykonania 15 min)... 16 Zadanie 8 (czas wykonania 15 min)... 16
Informacje o module Opis modułu W module poznasz zaawansowane zastosowania języka MDX. Znajdziesz opisy dla funkcji: IIF, Filter, StrToValue. Poznasz także operacje na zbiorach w przestrzeni wielowymiarowej, funkcje Lead i Lag pozwalające na odczyt elementu poprzedniego i następnego, operator zakresu (:). Nauczysz się wyznaczania prostej średniej kroczącej i obliczanie agregacji porównawczych względem elementów poprzednich (porównanie bieżącego roku do lat poprzednich). Cel modułu Celem modułu jest nauczenie zaawansowanych funkcjonalności języka MDX, raportów porównawczych, a także operacji na zbiorach w wielowymiarowych kostkach danych. Uzyskane kompetencje Po zrealizowaniu modułu będziesz: wiedział jak używać podstawowych i zaawansowanych funkcji języka MDX potrafił używać na zbiorach operującymi na wielu hierarchiach zdolny do przyswojenia innych funkcji na podstawie dokumentacji on-line Wymagania wstępne Przed przystąpieniem do pracy z tym modułem powinieneś: znać składnię języka MDX potrafić użyć funkcji języka MDX: Children, Members, FirstChild, LastChild, DefaultMember, Cousin, Distinct, Except, DrillDownLevel, NonEmpty, Order, TopCount, BottomCount, Filter, CrossJoin, NonEmptyCrossJoin rozumieć jak definiowane są nowe elementy i agregaty kalkulowane w wielowymiarowej kostce Mapa zależności modułu Zgodnie z mapą zależności przedstawioną na Rys. 1, przed przystąpieniem do realizacji tego modułu należy zapoznać się z materiałem zawartym w modułach 3, 4, 5, 6, 7. Strona 2/17
Rys. 1 Mapa zależności modułu Strona 3/17
Przygotowanie teoretyczne Podstawy teoretyczne Zapytanie MDX posiada następującą składnię (w uproszczonej wersji): [ <specyfikacja formuly> [,<specyfikacja formuly> ]] [<specyfikacja osi> [,<specyfikacja osi> ]] FROM [<specyfikacja kostki>] [WHERE [<specyfikacja warunków]] Na każdej osi jest lista punków w przestrzeni wielowymiarowej <specyfikacja osi>:: <zbiór punktów> ON <nazwa osi> Nazwa osi dopuszcza następujące wartości: <nazwa osi>:: COLUMNS ROWS PAGES SECTIONS CHAPTERS AXIS (index) Zapytanie którego wynikiem jest przestrzeń dwuwymiarowa: { <KOLEKCJA> } ON COLUMNS, { <KOLEKCJA> } ON ROWS FROM [<KOSTKA DANYCH>] WHERE (<WARUNEK>) Składnia funkcji Children: { [Wymiar].Children } { [Poziom w wymiarze].children } { [Hierarchia].Children } { [Element].Children } Składnia funkcji Members: { [Wymiar].Members } { [Poziom w wymiarze].members } { [Poziom w hierarchii].members } { [Hierarchia].Members } Składnia funkcji FirstChild: [Hierarchia].FirstChild [Poziom].FirstChild [Element w hierarchii].firstchild Składnia funkcji LastChild: [Hierarchia].LastChild [Poziom].LastChild [Element w hierarchii].lastchild Składnia funkcji DefaultMember: [Hierarchia].DefaultMember [Poziom].DefaultMember Składnia funkcji Cousin: Cousin( [Element], [Element na wyższym poziomie] ) Składnia funkcji Distinct: Distinct( KOLEKCJA ) Składnia funkcji Except: Except( KOLEKCJA, KOLEKCJA ) Składnia funkcji DrillDownLevel: Strona 4/17
DrillDownLevel( [Wymiar] ) DrillDownLevel( [Poziom] ) DrillDownLevel( [Element] ) Składnia funkcji NonEmpty: NonEmpty( KOLEKCJA ) Składnia funkcji NonEmpty: Order( KOLEKCJA, [Agregat], TYP_SORTOWANIA ) Składnia funkcji TopCount i BottomCount: TopCount( KOLEKCJA, N, AGREGAT ) BottomCount( KOLEKCJA, N, AGREGAT ) Składnia funkcji Filter: Filter( KOLEKCJA, WARUNEK ) Składnia funkcji CrossJoin: CrossJoin( KOLEKCJA, KOLEKCJA ) KOLEKCJA * KOLEKCJA Składnia funkcji NonEmptyCrossJoin: NonEmptyCrossJoin( KOLEKCJA, KOLEKCJA ) Składnia MEMBER AS dla agregatów: MEMBER [Measures].[Nowy agregat] AS ' WYRAZENIE ' Składnia MEMBER AS dla elementów: MEMBER [Wymiar].[Poziom].[Nowy element] AS ' WYRAZENIE ' MEMBER [Wymiar].[Hierarchia].[Nowy element] AS ' WYRAZENIE ' Składnia funkcji Properties: [Wymiar].Properties("Wlasnosc") [Hierarchia].Properties("Wlasnosc") [Poziom w wymiarze].properties("wlasnosc") [Poziom w hierarchii].properties("wlasnosc") Porady praktyczne Uwagi ogólne Każde zapytanie MDX znajdujące się w instrukcji spróbuj wykonać i przeanalizować, co dokładnie otrzymujemy jako wynik. O ile to możliwe, spróbuj korzystać z pomocy online dotyczącej języka MDX (link znajduje się w dodatkowych źródłach informacji). Obiekty wielowymiarowe najlepiej ćwiczyć na trzech wymiarach. Można wyobrazić sobie kostkę sześcienną, na ścianach są odpowiednio: klient, produkt, czas, wewnątrz kostki są agregaty. Każdy punkt kostki posiada pewne współrzędne którymi są wspomniane wymiary. Za pomocą takiego modelu łatwiej zrozumieć takie funkcje jak: Lag, Lead, CurrentMember, Parent. Uwagi dla studenta Jesteś przygotowany do realizacji laboratorium jeśli: znasz różnicę pomiędzy wymiarem, hierarchią, poziomem, atrybutem rozumiesz jak używać zaawansowanych funkcji języka MDX umiesz definiować nowe agregaty i elementy kalkulowane Strona 5/17
potrafisz pisać zapytania używając funkcji CrossJoin operującej na wielu hierarchiach i poziomach Przed realizacją każdego punktu przeczytaj go dokładnie, a następnie przeanalizuj dokładnie wyniki każdego zapytania. Jeżeli nie rozumiesz jak działa określona funkcja lub składnia, porównaj z dokumentacją on-line i poprzednimi przykładami. Pamiętaj o zapoznaniu się z uwagami i poradami zawartymi w tym module. Upewnij się, że rozumiesz omawiane w nich zagadnienia. Jeśli masz trudności ze zrozumieniem tematu zawartego w uwagach, przeczytaj ponownie informacje z tego rozdziału i zajrzyj do notatek z wykładów. Dodatkowe źródła informacji 1. George Spofford: "MDX Solutions: With Microsoft SQL Server Analysis Services" 2. Mark Whitehorn, Robert Zare, Mosha Pasumansky: "Fast Track to MDX" 3. Strona internetowa: http://msdn.microsoft.com/en-us/library/ms145595.aspx 4. Strona internetowa: http://www.mosha.com/msolap/articles/mdxforeveryone.htm Strona 6/17
Laboratorium podstawowe W hurtowni danych i wszystkich systemach analitycznych system raportujący odgrywa bardzo ważną rolę. Bez dobrej wizualizacji nie ma sensu przygotowywanie, zbieranie informacji, analizy schematu i projektowanie procesu ETL. W systemie bazodanowym podstawowym językiem do wyciągania interesujących nas podsumowań jest SQL, natomiast w systemach OLAP język ten to MDX. Projektowanie bardzo prostych raportów jest możliwe za pomocą tabel przestawnych, niestety większość naprawdę przydatnych rzeczy nie ogranicza się do tabel przestawnych. W firmie Adventure Works mamy do zaprojektowania raporty podsumowujące aktualną działalność firmy, a także działalność w odniesieniu do danych historycznych. Potrzebne są porównania kwartałów i użycie średniej kroczącej, aby przekonać się o trendach zbieranych danych. W kolejnych krokach przedstawimy funkcje i typowe struktury, dzięki którym możliwe będzie wykonanie zadań zawartych w laboratorium rozszerzonym. Na laboratorium zapoznamy się z funkcjami IIF, StrToValue. Kolejno poznamy funkcję NextMember, PrevMember, Lead, Lag za pomocą których wydobędziemyy poprzednie lub kolejne elementy w stosunku do aktualnie rozpatrywanego. Następnie nauczymy się wykonywać operacje na obiektach wielowymiarowych i używać funkcji Sum i Avg to obliczaniaa średniej kroczącej. Na końcu zaprezentujemy raporty porównujące dane agregacyjne w ramach czasowych. Zadanie 1. Połączenie do bazy 2. Funkcja IIF Tok postępowania Uruchom SQL Server Management Studio. W oknie Object Explorer kliknij Connect i z rozwijanego menu wybierz Analysis Services. Wpisz nazwę serwera (localhost) i kliknij na przycisk Connect. Rozwiń dostępne bazy danych. Kliknij prawym przyciskiem myszy na bazie Adventure Works DW i z kontekstowego menu wybierz New Query -> MDX. Za pomocą funkcji IIF możemy wyświetlić jedną z dwóch wartości w zależności od warunku podanego jako pierwszy parametr: IIF( WARUNEK, WARTOSC_JEZELI_TAK, WARTOSC_JEZELI_NIE ) W podanym niżej przykładzie zamieniamy konkretne wartości na przyporządkowane oznaczenia Znana lub Nieznana. MEMBER [Measures].[Waga] AS 'IIF([Product].[Product].Properties( "Weight"" )="Unknown", {[Measures].[Waga], [Measures].[Order Quantity]} ON COLUMNS, {NonEmpty([Product].[Product].Children)} ON ROWS "Nieznana","Znana")' Jako argumenty funkcji IIF możemy także używać wyrażeń, jak to pokazano na poniższym przykładzie. MEMBER [Measures].[Waga Sztuki] AS 'IIF([Product].[Product].Properties("Weight")="Unknown", Strona 7/17
3. Funkcja StrToValue 4. Funkcja NextMember, "Nieznana",[Product].[Product].Properties("Weight"))' MEMBER [Measures].[Waga Calkowita] AS 'IIF([Product].[Product].Properties("Weight")="Unknown", "Nieznana",[Product].[Product].Properties("Weight") * MEMBER [Measures].[Liczba Sztuk] AS '[Measures].[Order Quantity]' {[Measures].[Waga Sztuki], [Measures].[Waga Calkowita], [Measures].[Liczba Sztuk]} ON COLUMNS, {NonEmpty([Product].[Product].Children)} ON ROWS Wykonaj powyższe zapytania. Niekiedy właściwości są zapisane jako łańcuchy znaków, choć w rzeczywistości są to liczby. Można użyć funkcji StrToValue aby przekonwertować łańcuch na wartość: StrToValue( LANCUCH ) W podanym niżej przykładzie wszystkie produkty oznaczone są jako Expensive mimo, że [Dealer Price] nie jest większy od 500. MEMBER [Measures].[Dealer Price] AS '[Product].[Product].CurrentMember.Properties("Dealer Price")' MEMBER [Measures].[Price Cheap] AS 'IIF([Product].[Product].CurrentMember.Properties("Dealer Price")>500,"Expensive","Cheap")' {[Measures].[Dealer Price], [Measures].[Price Cheap], [Measures].[Order Quantity]} ON COLUMNS, {NonEmpty([Product].[Product].Children)} ON ROWS Kolejny przykład pokazuje prawidłowe użycie funkcji StrToValue. Wpisz i przeanalizuj zapytanie: MEMBER [Measures].[Dealer Price] AS '[Product].[Product].CurrentMember.Properties("Dealer Price")' MEMBER [Measures].[Price Cheap] AS 'IIF(StrToValue([Product].[Product].CurrentMember.Properties("Deal er Price"))>500,"Expensive","Cheap")' {[Measures].[Dealer Price], [Measures].[Price Cheap], [Measures].[Order Quantity]} ON COLUMNS, {NonEmpty([Product].[Product].Children)} ON ROWS Wykonaj powyższe zapytania. Za pomocą funkcji NextMember, PrevMember, Lead, Lag można wyznaczyć poprzednie lub kolejne elementy w stosunku do elementu Strona 8/17
PrevMember, rozpatrywanego: Lead, Lag [E Element].PrevMember [Element].NextMember [Element].Lead( LICZBA ) [Element].Lag( LICZBA ) Funkcja Lead(N) odpowiada funkcji Lag(-N), tak jak funkcja Lag(N) odpowiada funkcji Lead(-N). W niżej podanym przykładzie dla każdego wiersza wyznaczamy poprzedni kwartał. Wpisz zapytanie. MEMBER [Measures].[Last Quarter] AS 'IIF([Date].[Fiscal].PrevMember=null, {[Measures].[Last Quarter], [Measures].Members} ON COLUMNS, {[Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS MEMBER [Measures].[Last 5 Quarter] AS MEMBER [Measures].[Last Quarter] AS MEMBER [Measures].[Next Quarter] AS MEMBER [Measures].[Next 5 Quarter] AS "-",[Date].[Fiscal].PrevMember.Name)' Aby odwołać się do elementu aktualnego użyliśmy [Date].[Fiscal], a nie [Date].[Fiscal].[Fiscal Quarter]. Przy użyciu hierarchii, element aktualny jest związany tylko z wymiarem i hierarchią. Tylko przy użyciu poziomu leżącego bezpośrednio pod wymiaremm element aktualny jest związany z tym wymiarem i poziomem. Ma to związek z drilowaniem danych. Dla hierarchii możemy użyć funkcji DrillDownLevel, a wtedy nie ma sensu odwoływać się do konkretnego poziomu, ponieważ na jednej osi może być rozpatrywanych wielee poziomów z jednej hierarchii. W kolejnym przykładzie pokazujemy element znajdujący się 5 elementów wcześniej, poprzedni, następny, znajdujący się 5 elementów później. 'IIF([Date].[Fiscal].Lag(5)=null, "-",[Date].[Fiscal].Lag(5).Name)' 'IIF([Date].[Fiscal].PrevMember=null, "-",[Date].[Fiscal].PrevMember.Name)' 'IIF([Date].[Fiscal].NextMember=null, "-",[Date].[Fiscal].NextMember.Name)' 'IIF([Date].[Fiscal].Lead(5)=null, "-",[Date].[Fiscal].Lead(5).Name)' {[Measures].[Last 5 Quarter], [Measures].[Last Quarter], [Measures].[Next Quarter], [Measures].[Next 5 Quarter], [Measures].Members} ON COLUMNS, Strona 9/17
5. Operacje na obiektach wielowymiarowyc h {[Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS Wykonaj powyższe zapytania. ( ( Rozpatrywany obiekt w przestrzeni zawiera wiele wartości w zależności od innych wymiarów. Aby uzyskać informacje o wartościach dla określonych krotek, należy użyć notacji krotkowej: ELEMENT, AGREGAT ) KOLEKCJA, AGREGAT ) W poniższym przykładzie wyznaczamy wartości [Order Quantity] dla [Europe],[Pacific], a także sumaryczne. MEMBER [Measures].[Europe Order Quantity] AS '([Sales Territory].[Sales Territory].[Sales Territory Group].&[Europe],[Measures].[Order Quantity]) )' MEMBER [Measures].[Pacific Order Quantity] AS '([Sales Territory].[Sales Territory].[Sales Territory Group].&[Pacific],[Measures].[Order Quantity] ])' {[Measures].[Europe Order Quantity], [Measures].[Pacific Order Quantity], [Measures].[Order Quantity]} ON COLUMNS, {[Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS W kolejnym przykładzie wyznaczamy [Order Quantity] dla aktualnego i poprzedniego kwartału używając funkcji PrevMember. MEMBER [Measures].[Last Quarter Order Quantity] AS '([Date].[Fiscal].PrevMember, MEMBER [Measures].[Diff Order Quantity] AS '[Measures].[Order Quantity] - [Measures].[Last Quarter Order Quantity]' {[Measures].[Last Quarter Order Quantity], [Measures].[Order Quantity], [Measures].[Diff Order Quantity]} ON COLUMNS, {[Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS Następny przykład ilustruje wykorzystanie funkcji Parent do pokazywania procentowego udziału elementu w elementach leżących na poziomach wyżej. MEMBER [Measures].[Actual Semester Order Quantity] AS '([Date].[Fiscal].Parent,[Measures].[Order MEMBER [Measures].[Actual Year Order Quantity] AS Quantity])' '([Date].[Fiscal].Parent.Parent, Strona 10/17
6. Wykorzystanie funkcji do obliczania agregacji MEMBER [Measures].[Order Quantity in Semester Percent] AS '[Measures].[Order Quantity]/[Measures].[Actual Semester Order Quantity]', FORMAT='PERCENT' MEMBER [Measures].[Order Quantity in Year Percent] AS '[Measures].[Order Quantity]/[Measures].[Actual Year Order Quantity]', FORMAT='PERCENT' {[Measures].[Actual Semester Order Quantity], [Measures].[Actual Year Order Quantity], [Measures].[Order Quantity], [Measures].[Order Quantity in Semester Percent], [Measures].[Order Quantity in Year Percent]} ON COLUMNS, {[Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS Wykonaj powyższe zapytania. Sum( KOLEKCJA, AGREGAT ) Można obliczyć sumę poprzedniego i z wykorzystaniem funkcji Sum: W poniższym przykładzie przedstawiamy i poprzedniego agregatu. MEMBER [Measures].[Order Quantity Sum2] AS 'Sum({[Delivery Date].[Fiscal].PrevMember, [Delivery Date].[Fiscal].CurrentMember} }, {[Measures].[Order Quantity], [Measures].[Order Quantity Sum2]} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS Funkcja Sum przyjmuje dwa parametry: pierwszym jest element lub kolekcja, a drugim jest agregat który zostanie wyznaczony dla każdego z tych elementów. W powyższym przykładzie odwołujemy się tylko do aktualnego i poprzedniego elementu. W kolejnym przykładzie obliczamy średnią kroczącą (Simple Moving Average SMA) za pomocą funkcji Lag, a także znaku dwukropka jako operatora zakresu. Operator zakresu zwraca wszystkie elementy pomiędzy elementami krańcowymi rozdzielonymi znakiem dwukropka. Kolekcja: {[Delivery Date].[Fiscal].Lag(4) : [Delivery Date].[Fiscal].CurrentMember} jest równoważna: {[Delivery Date].[Fiscal].Lag(4), [Delivery Date].[Fiscal].Lag(3), [Delivery Date].[Fiscal].Lag(2), [Delivery Date].[Fiscal].Lag(1), [Delivery Date].[Fiscal].CurrentMember} aktualnego elementu obliczenie aktualnego Strona 11/17
MEMBER [Measures].[Order Quantity SMA5] AS 'Avg({[Delivery Date].[Fiscal].Lag(3) : {[Measures].[Order Quantity], [Measures].[Order Quantity SMA5]} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS MEMBER [Measures].[Order Quantity SMA5] AS 'Avg({[Delivery Date].[Fiscal].Lag(3): {[Measures].[Order Quantity], [Measures].[Order Quantity SMA5]} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS WHERE ([Product].[Category].[Category].[Accessories]) MEMBER [Measures].[Order Quantity Accessories] AS '([Product].[Category].[Category].[Accessories], MEMBER [Measures].[Order Quantity SMA5] AS 'Avg({[Delivery Date].[Fiscal].Lag(5): {[Measures].[Order Quantity Accessories], [Measures].[Order Quantity SMA5]} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS Idąc dalej tym krokiem możemy dodać kolejne elementy do raportu: [Delivery Date].[Fiscal].CurrentMember} }, Powyżej przedstawiona średnia krocząca jest bardzo często wykorzystywana w rozmaitych raportach z dziedziny ekonomii. Zapytanie przedstawia liczbę jednostek dla wszystkich produktów. Jeżeli chcielibyśmy średnią tylko dla pewnych określonych elementów, możemy dodać frazę WHERE. [Delivery Date].[Fiscal].CurrentMember} }, Dodanie frazy WHERE nie rozwiązuje sprawy, ponieważ nie ma możliwości wyświetlenia SMA5 (Simple Moving Average Algebraiczna Średnia Krocząca) dla innych kategorii produktu na jednym raporcie, poniżej prezentujemy rozwiązanie w którym zmodyfikowana została fraza MEMBER AS. [Delivery Date].[Fiscal].CurrentMember} }, ([Product].[Category].[Category].[Accessories], [Measures].[Order Quantity]))' Strona 12/17
7. Użycie wielu poziomów hierarchii do obliczeń agregacyjnych MEMBER [Measures].[Order Quantity Accessories] AS '([Product].[Category].[Category].[Accessories], MEMBER [Measures].[Order Quantity Bikes] AS '([Product].[Category].[Category].[Bikes], MEMBER [Measures].[Order Quantity SMA5 Accessories] AS 'Avg({[Delivery Date].[Fiscal].Lag(5): [Delivery Date].[Fiscal].CurrentMember} }, ([Product].[Category].[Category].[Accessories], [Measures].[Order Quantity]))' MEMBER [Measures].[Order Quantity SMA5 Bikes] AS 'Avg({[Delivery Date].[Fiscal].Lag(5): [Delivery Date].[Fiscal].CurrentMember} }, ([Product].[Category].[Category].[Bikes], [Measures].[Order Quantity]))' {[Measures].[Order Quantity Bikes], [Measures].[Order Quantity SMA5 Bikes], [Measures].[Order Quantity Accessories], [Measures].[Order Quantity SMA5 Accessories] ]} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS Trudno przewidzieć wszystkie kategorie produktów, dlatego w dalszym kroku wyświetlamy wszystkie kategorie produktu na osi X, wszystkie kwartały na osi Y, a w krotkach wartości średniej kroczącej. MEMBER [Measures].[Order Quantity SMA5] AS 'Avg({[Delivery Date].[Fiscal].Lag(5): [Delivery Date].[Fiscal].CurrentMember}, {[Product].[Category].[Category].Members} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS WHERE ([Measures].[Order Quantity SMA5]) Wykonaj powyższe zapytania. W poprzednich przykładach sytuacja była taka, że rozpatrywane elementy na osi Y (kwartały) należały do jednego poziomu. Co będzie, jeżeli użyjemy funkcji DrillDownLevel i jednocześnie będziemy rozpatrywać funkcję Lag? MEMBER [Measures].[Order Quantity SMA5] AS 'Avg({[Delivery Date].[Fiscal].Lag(5): [Delivery Date].[Fiscal].CurrentMember} }, Strona 13/17
8. Raporty zależne w czasie {[Product].[Category].[Category].Members} ON COLUMNS, {DrillDownLevel([Delivery Date].[Fiscal].[Fiscal Semester].Members)} ON ROWS WHERE ([Measures].[Order Quantity SMA5]) Obliczenia zostały wykonane bez błędu widocznego na ekranie, czy są jednak logicznie spójne? Dla każdego kwartału oczekujemy średniej kroczącej z 5 ostatnich kwartałów. Dla każdego semestru oczekujemy średniej dla 5 ostatnich semestrów. Po wykonaniu zapytania dotyczącego semestrów można już upewnić się, że dane są spójne: MEMBER [Measures].[Order Quantity SMA5] AS 'Avg({[Delivery Date].[Fiscal].Lag(5): [Delivery Date].[Fiscal].CurrentMember} }, {[Product].[Category].[Category].Members} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Semester].Members} ON ROWS WHERE ([Measures].[Order Quantity SMA5]) Wykonaj powyższe zapytania. Jednym z celów raportów jest porównanie wartości aktualnych z pewnymi przeszłymi. W poprzednich punktach prezentowaliśmy raport który obliczał różnicę z aktualnego kwartału w stosunku do jednego kwartału wcześniej. Teraz pokażemy raport, który oblicza różnicę aktualnego kwartału do odpowiedniego kwartału rok wcześniej zostanie używa funkcja Cousin. Pierwsze zapytanie obrazuje, jak należy obliczyć odpowiadający semestr z poprzedniego roku. MEMBER [Measures].[Order Quantity Parent Parent] AS 'Cousin([Delivery Date].[Fiscal].CurrentMember, [Delivery Date].[Fiscal].Parent.Parent.PrevMember).Name' {[Measures].[Order Quantity Parent Parent]} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS Została dwukrotnie użyta funkcja Parent, ponieważ w hierarchii [Fiscal] rok jest dwa poziomy nad kwartałem (rok, semestr, kwartał, miesiąc, data). Kolejne zapytanie realizuje już wspomniane zadanie. MEMBER [Measures].[Order Quantity Prev] AS '(Cousin([Delivery Date].[Fiscal].CurrentMember, [Delivery Date].[Fiscal].Parent.Parent.PrevMember), MEMBER [Measures].[Order Quantity Prev Quater Diff] AS '[Measures].[Order Quantity] Strona 14/17
- [Measures].[Order Quantity Prev]' {[Product].[Category].[Category].Members} ON COLUMNS, {[Delivery Date].[Fiscal].[Fiscal Quarter].Members} ON ROWS WHERE ([Measures].[Order Quantity Prev Quater Diff]) Wykonaj powyższe zapytania. Strona 15/17
Laboratorium rozszerzone Do podejmowania decyzji potrzebne są przekrojowe dane, które powinny być dostępne dla użytkowników biznesowych. Z tego powodu należy przygotować szereg raportów w postaci zapytań MDX gotowych do uruchomienia (poprzez przeglądarkę lub bezpośrednio w SQL Server Management Studio). Przedstawione niżej zadania są raportami, które pochodzą od użytkowników biznesowych. Laboratorium rozszerzone zawiera opcjonalne raporty do wykonania. Każde zadanie jest niezależne, zadania zostały ustawione od najłatwiejszych do najtrudniejszych. Dla każdego zadania podany jest orientacyjny czas wykonania. Wykonaj następujące raporty w języku MDX: Zadanie 1 (czas wykonania 10 min) Dla kostki Sales Summary wypisz wszystkie produkty, dla których wartość agregatu Sales Amount była większa niż wartość Sales Amount dla produktu pierwszego. Zadanie 2 (czas wykonania 10 min) Dla kostki Sales Summary wypisać wszystkie te produkty, dla których Sales Amount było większe w 2006 niż w 2007 roku. Zadanie 3 (czas wykonania 12 min) Dla kostki Sales Summary wypisz SMA6 z interwałem miesięcznym (oś Y) dla agregatu Sales Amount w zależności od kategorii produktu i kategorii promocji (oś X). Zadanie 4 (czas wykonania 12 min) Dla kostki Sales Summary wypisz trzy najlepsze miesiące roku 2003, które były lepsze pod względem agregatu Sales Amount od odpowiedniego miesiąca roku 2002 (znajdujemy trzy miesiące, dla których różnica w agregacie Sales Amount między miesiącem roku 2003 i 2002 była największa). Zadanie 5 (czas wykonania 15 min) Dla kostki Sales Summary wypisz 5 najlepszych produktów pod względem procentowego zwiększenia sprzedaży z roku 2003 na 2004. Zadanie 6 (czas wykonania 15 min) Dla kostki Sales Summary napisz raport porównujący wszystkie kwartały aktualnego roku do poszczególnych kwartałów kolejnych lat. Porównywany agregat to Sales Amount. Na osi Y powinny znaleźć się kwartały aktualnego roku, a na osi X kolejne lata. W krotkach powinny znaleźć się liczby oznaczające, o ile procent agregat Sales Amount jest większy lub mniejszy (znak minus) od odpowiadającego kwartału w roku podanym na osi X. Zadanie 7 (czas wykonania 15 min) Dla kostki Sales Summary napisz raport wyświetlający te wszystkie produkty i agregaty dla nich, które miały większą sprzedaż (Sales Amount) w drugim kwartale roku 2003 niż w trzecim kwartale roku 2003. Posortuj wynik wg całkowitego kosztu produktu (Total Product Cost). Zadanie 8 (czas wykonania 15 min) Dla kostki Sales Summary wypisać wszystkie te kwartały i agregaty dla których udział procentowy w danym roku przekroczył 27% pod względem Sales Amount. Określony kwartał zostanie Strona 16/17
wyświetlony, jeżeli Sales Amount dla tego kwartału podzielony przez Sales Amount dla roku będzie większe od 0,27. Strona 17/17