Klauzula MODEL w języku SQL w środowisku Oracle 15.05.2012
Zakres Wprowadzenie do klauzuli MODEL Zastosowanie Zalety Lokalizacja klauzuli w poleceniu SELECT Podstawowe pojęcia Partycje Wymiary Miary Składnia klauzuli Opcje domyślne Reguły Zastosowanie Kolejność Iteracje Przykłady zastosowania Korzyści ze stosowania MODEL
Wprowadzenie Język SQL doskonale nadaje się do wyszukiwania danych. Jednak standardowa wersja polecenie SELECT ma ograniczone możliwości w operowaniu na wyszukanych danych: Dane można łatwo wybierać, filtrować, sortować. Obliczenia można wykonywać: Wyrażeniami Funkcjami jednowierszowymi i grupowymi Problemem jest dostęp do innych rekordów
Wprowadzenie Operacje pomiędzy polami w różnych wierszach, typowe dla np. MS Excel, nie są typowe dla SQL są jednak możliwe poprzez: Zapytania hierarchiczne od Oracle 7 Funkcje analityczne od Oracle 8.1.6 Klauzulę MODEL od Oracle 10g
Wprowadzenie Klauzula MODEL pozwala definiować, jako wynik zapytania, tablice wielowymiarowe. Następnie można stosować do tych tablic reguły umożliwiające wyznaczanie nowych wartości. Umożliwia wykonywanie obliczeń międzywierszowych, poprzez dostęp do kolumn w wierszu w taki sposób, jakby to były komórki w tablicy. Można zauważyć analogię do arkuszy kalkulacyjnych (np. MS Excel), co uzasadnia alternatywną nazwę klauzuli MODEL SPREADSHEET.
Wprowadzenie Zalety w stosunku do obliczeń poza silnikiem bazy: Wydajność Skalowalność Zarządzanie Tworzenie wielowymiarowej tablicy mapowanie kolumn na: Partycje (partitions) Wymiary (dimensions) Miary (measures)
Podstawowe pojęcia Partycje definiują lokalne bloki zbioru wynikowego w sposób podobny do partycji w funkcjach analitycznych. Reguły klauzuli MODEL są stosowane do komórek każdej partycji. Wymiary identyfikują każdy wymiar komórki w partycji. Kolumny te określają właściwości (cechy) takie jak: daty, regiony, nazwy produktów. Miary zwykle zawierają wartości numeryczne, takie jak jednostki sprzedaży lub kosztu. Każda komórka jest określana poprzez pełną kombinację wymiarów.
Składnia <prior clauses of SELECT statement> MODEL [RETURN [ALL UPDATED] ROWS] [PARTITION BY (<cols>)] DIMENSION BY (<cols>) MEASURES (<cols>) [IGNORE NAV] [KEEP NAV] [RULES [UPSERT UPDATE] [AUTOMATIC ORDER SEQUENTIAL ORDER] [ITERATE (n) [UNTIL <condition>] ] ( <cell_assignment> = <expression>... )
Dane CREATE VIEW sales_view AS SELECT country_name country, prod_name prod, calendar_year year, SUM(amount_sold) sale, COUNT(amount_sold) cnt FROM sales, times, customers, countries, products WHERE sales.time_id = times.time_id AND sales.prod_id = products.prod_id AND sales.cust_id = customers.cust_id AND customers.country_id = countries.country_id GROUP BY country_name, prod_name, calendar_year;
Reguły Aby utworzyć reguły na wielowymiarowych tablicach, należy wyrazić je w wartościach wymiarów. Reguły mogą wykorzystywać symbole wieloznaczne (wild cards) oraz pętle FOR. Obliczenia budowane z wykorzystaniem klauzuli MODEL: Zwiększają wydajność tradycyjnych arkuszy kalkulacyjnych poprzez wykonywanie analizy wewnątrz bazy danych Zwiększają czytelność poprzez symboliczne odwołania Umożliwiają skalowalność Pozwalają na wygodniejsze zarządzanie
Reguły Dostęp do komórek (ich współrzędne) może być realizowany poprzez zapis pozycyjny lub symboliczny: sales[country='spain',year=2001] = sales['spain',2000]+ sales['spain',1999] Reguły mogą pracować na poszczególnych komórkach lub na zestawach (zakresach) komórek, np.: sales[country='spain',year=2001] = MAX(sales)['Spain',year BETWEEN 1997 AND 2000]
Wild card Opcje ANY i IS ANY pozwala dopuścić / zastąpić wszystkie wartości w wymiarze. Wszystkie wartości (wliczając null) spełniają warunek ANY. sales[any, 2001] = sales['japan', 2000] sales[country IS ANY, 2001] = sales['japan', 2000]
Funkcja CV Funkcja CV (lub CURRENTV), umieszczona po prawej stronie reguły, daje dostęp do wartości kolumny wymiaru dla komórki, do której istnieje odwołanie po lewej stronie reguły (przekazuje wartości z lewej strony na prawą). Pozwala na zamianę kilku reguł, wykonujących podobne obliczenia, w pojedynczą regułę. sales[country='spain', year=2002] = 1.2 * sales['spain', 2001], sales[country='italy', year=2002] = 1.2 * sales['italy', 2001], sales[country='japan', year=2002] = 1.2 * sales['japan', 2001] sales[country IN ('Spain', 'Italy', 'Japan'), year=2002] = 1.2 * sales[cv(country), 2001] Zapisy równoważne: CV(country), CV(), CURRENTV()
Order by Dla reguł uaktualniających zestaw komórek, wyniki mogą zależeć od kolejności wartości wymiaru. Możliwe jest wymuszenie konkretnej kolejności za pomocą klauzuli ORDER BY: sales[country IS ANY, year BETWEEN 2000 AND 2003] ORDER BY year = 1.05 * sales[cv(country), CV(year)-1] W ten sposób kolejne lata będą przetwarzane w narastającej kolejności.
Funkcja CV Funkcja CV może być także wykorzystana w operacjach arytmetycznych. SELECT prod, year, growth, pct FROM sales_view WHERE lower(prod) LIKE '%phone%' MODEL RETURN UPDATED ROWS PARTITION BY (prod) DIMENSION BY (country, year) MEASURES (sale sales, 0 growth, 0 pct) (growth['spain', year>1999] = sales[cv(),cv()] Sales[CV(),CV()-1], pct['spain', year>1999] = round(( sales[cv(),cv()] sales[cv(),cv()-1] ) / sales[cv(),cv()-1],2) ) ORDER BY prod, year;
Funkcja CV PROD YEAR GROWTH PCT -------------------------------------------------- ---------- ---------- ---------- Model C93822D Wireless Phone Battery 2000-197,67 -,17006065 Model C93822D Wireless Phone Battery 2001 474,42,491790024 Model C9827B Cordless Phone Battery 2000-229,37 -,10389546 Model C9827B Cordless Phone Battery 2001 797,08,402905481 Model K3822L Cordless Phone Battery 2000-376,07 -,21264794 Model K3822L Cordless Phone Battery 2001 682,55,490182701 Model K8822S Cordless Phone Battery 2000-443,43 -,1390769 Model K8822S Cordless Phone Battery 2001 1386,52,505116669 S27273M Extended Use w/l Phone Batt. 2000 2153,53 1,09664163 S27273M Extended Use w/l Phone Batt. 2001 541,59,131540726
Funkcja CV Funkcja CV może być także wykorzystana w operacjach arytmetycznych. SELECT prod, year, to_char(growth,'999g990d99') AS growth, to_char(pct,'90d99') ' %' AS pct FROM sales_view WHERE lower(prod) LIKE '%phone%' MODEL RETURN UPDATED ROWS PARTITION BY (prod) DIMENSION BY (country, year) MEASURES (sale sales, 0 growth, 0 pct) (growth['spain', year>1999] = sales[cv(),cv()] Sales[CV(),CV()-1], pct['spain', year>1999] = round(( sales[cv(),cv()] sales[cv(),cv()-1] ) / sales[cv(),cv()-1],2) ) ORDER BY prod, year;
Funkcja CV PROD YEAR GROWTH PCT -------------------------------------------------- ---------- ----------- -------- Model C93822D Wireless Phone Battery 2000-197,67-0,17 % Model C93822D Wireless Phone Battery 2001 474,42 0,49 % Model C9827B Cordless Phone Battery 2000-229,37-0,10 % Model C9827B Cordless Phone Battery 2001 797,08 0,40 % Model K3822L Cordless Phone Battery 2000-376,07-0,21 % Model K3822L Cordless Phone Battery 2001 682,55 0,49 % Model K8822S Cordless Phone Battery 2000-443,43-0,14 % Model K8822S Cordless Phone Battery 2001 1 386,52 0,51 % S27273M Extended Use w/l Phone Batt. 2000 2 153,53 1,10 % S27273M Extended Use w/l Phone Batt. 2001 541,59 0,13 %
MODEL DIMENSION BY(prod, year) MEASURES (sales s) RULES UPSERT (s[any, 2000] = s[cv(prod), CV(year)-1]*2, s[vcr, 2002] = s[vcr, 2001]+s[vcr, 2000], s[dvd, 2002] = AVG(s)[CV(prod), year < 2001])
Przykład 1 SELECT SUBSTR(country,1,20) country, SUBSTR(prod,1,15) prod, year, sales FROM sales_view WHERE country IN ('Italy','Japan') MODEL RETURN UPDATED ROWS PARTITION BY (country) DIMENSION BY (prod, year) MEASURES (sale sales) RULES ( sales['bounce', 2002] = sales['bounce', 2001] + sales['bounce', 2000], sales['y Box', 2002] = sales['y Box', 2001], sales['2_products',2002] = sales['bounce',2002] + sales['y Box',2002]) ORDER BY country, prod, year; COUNTRY PROD YEAR SALES -------------------- --------------- ---------- ---------- Italy 2_Products 2002 90387.54 Italy Bounce 2002 9179.99 Italy Y Box 2002 81207.55 Japan 2_Products 2002 101071.96 Japan Bounce 2002 11437.13 Japan Y Box 2002 89634.83
upsert i update Opcja UPSERT (domyślna) umożliwia tworzenie wartości komórek, które nie istnieją w danych źródłowych: Jeżeli komórki istnieją w zbiorze danych, będą uaktualnione Jeżeli nie istnieją, zostaną dodane do zbioru. UPDATE nie wstawia nowych wierszy. Można określić tę opcję globalnie, lub na poziomie poszczególnych reguł (wówczas nadpisuje ustawienie globalne). UPDATE sales['spain', 1999] = 3567.99, UPSERT sales['spain', 2001] = sales['spain', 2000] + sales['spain', 1999]
Kolejność reguł Klauzula AUTOMATIC ORDER umożliwia automatyczne określenie kolejności wykonywania reguł na podstawie zależności pomiędzy nimi. RULES AUTOMATIC ORDER {sales[c='spain', y=2001] = sales[c='spain', y=2000] + sales[c='spain', y=1999], sales[c='spain', y=2000] = 50000, sales[c='spain', y=1999] = 40000} Reguły 2 i 3 zostaną wykonane najpierw, bo od nich zależy wynik reguły 1. Domyślna opcja to: SEQUENTIAL ORDER.
Iteracje Wykonywanie reguł może przebiegać iteracyjnie będą wykonywane aż do spełnienia ostatniej reguły. Opcja ITERATE umożliwia podane liczby powtórzeń. Opcja UNTIL umożliwia podanie warunku kończącego. ITERATE (number_of_iterations) [ UNTIL (condition) ] Czterokrotne powtórzenie formuły s[x=1] = s[x=1]/2: MODEL DIMENSION BY (x) MEASURES (s) RULES ITERATE (4) (s[x=1] = s[x=1]/2)
Iteracje Zmienna systemowa ITERATION_NUMBER udostępnia numer iteracji. SELECT country, product, year, sales FROM sales_view MODEL PARTITION BY (country) DIMENSION BY (product, year) MEASURES (sales sales) IGNORE NAV RULES ITERATE(3) (sales['bounce', 2002 + ITERATION_NUMBER] = sales['bounce', 1999 + ITERATION_NUMBER]);
Pozostałe opcje IGNORE NAV traktuje niedostępne wartości (nie dostarczone do klauzuli MODEL przez zapytanie) jako 0. KEEP NAV zachowuje niedostępne wartości komórek niezmienione. (Domyślne) RETURN [ALL UPDATED] ROWS określenie, czy zwracane są wszystkie wyselekcjonowane wiersze, czy tylko te, które zostały zmodyfikowane przez reguły. Domyślna opcja: ALL.
Przykład 2 Sprzedaż dla Włoch i Hiszpanii oraz różnica pomiędzy nimi dla każdego produktu. Różnica zostanie umieszczona w nowych wierszach, dla których kraj zostanie podany jako: DIFF ITALY-SPAIN. SELECT SUBSTR(product,1,25) product, SUBSTR(country,1,15) country, sales FROM sales_view WHERE country IN ('Italy', 'Spain') GROUP BY product, country MODEL PARTITION BY (product) DIMENSION BY (country) MEASURES (SUM(sales) AS sales) RULES UPSERT (sales['diff ITALY-SPAIN'] = sales['italy'] - sales['spain']);
PRODUCT COUNTRY SALES ------------------------- --------------- ---------- Comic Book Heroes Italy 3434,92 Smash up Boxing Italy 10501,36 Model K8822S Cordless Pho Spain 11385,79 Model K8822S Cordless Pho Italy 29385,38 Model SM26273 Black Ink C Spain 10578,36 Envoy External 6X CD-ROM Italy 26001,09 Smash up Boxing Spain 5121,03 Bounce Italy 11654,77 Finding Fido Italy 3260,69 Model SM26273 Black Ink C Italy 32443,73 Bounce Spain 4521,9 Comic Book Heroes Spain 1894,88 Envoy External 6X CD-ROM Spain 10807,09 Finding Fido Spain 1446,69 Envoy External 6X CD-ROM DIFF ITALY-SPAI 15194 Model SM26273 Black Ink C DIFF ITALY-SPAI 21865,37 Comic Book Heroes DIFF ITALY-SPAI 1540,04 Smash up Boxing DIFF ITALY-SPAI 5380,33 Model K8822S Cordless Pho DIFF ITALY-SPAI 17999,59 Bounce DIFF ITALY-SPAI 7132,87 Finding Fido DIFF ITALY-SPAI 1814 Fly Fishing Italy 1331,11...
Przykład 3 Obliczenie, rok po roku, procentowe zmiany sprzedaży dla wybranych produktów: SELECT SUBSTR(country,1,10) country, SUBSTR(prod,1,12) prod, year, sales, growth FROM sales_view WHERE country='italy' MODEL RETURN UPDATED ROWS PARTITION BY (country) DIMENSION BY (prod, year) MEASURES (sale sales, 0 growth) RULES ( growth[prod in ('Bounce','Y Box','Mouse Pad'), year between 1998 and 2001] = 100 *( sales[cv(prod),cv(year)]-sales[cv(prod),cv(year)-1]) / sales[cv(prod), CV(year) -1] ) ORDER BY country, prod, year;
COUNTRY PROD YEAR SALES GROWTH ---------- ------------ ---------- ---------- ---------- Italy Bounce 1999 2474,78 Italy Bounce 2000 4333,69 75,1141516 Italy Bounce 2001 4846,3 11,828488 Italy Mouse Pad 1998 3055,69 Italy Mouse Pad 1999 4663,24 52,6084125 Italy Mouse Pad 2000 3662,83-21,45311 Italy Mouse Pad 2001 4747,9 29,6238155 Italy Y Box 1999 15215,16 Italy Y Box 2000 29322,89 92,7215356 Italy Y Box 2001 81207,55 176,942518
Pętle Wariant liczbowy zakres oraz inkrementacja: sales[for month FROM 1 TO 3 INCREMENT 1, 2013] = sales[currentv(), 2012] * 2 Wariant z listą wartości: sales[for month IN ('Styczeń', 'Luty', 'Marzec'), 2013] = sales[cv(month), 2012] * 2 sales[month IN ('Styczeń', 'Luty', 'Marzec'), 2013] = sales[cv(month), 2012] * 2
Przykład 4 Obliczenie sprzedaży konkretnych produktów w roku 2005, przy założeniu, że będzie o 30% większa niż w 2001: SELECT SUBSTR(country,1,20) country, SUBSTR(prod,1,15) prod, year, sales FROM sales_view WHERE country='italy' MODEL RETURN UPDATED ROWS PARTITION BY (country) DIMENSION BY (prod, year) MEASURES (sale sales) RULES ( sales[for prod in ('Mouse Pad','Bounce','Y Box'),2005] = 1.3 * sales[cv(prod), 2001] ) ORDER BY country, prod, year;
COUNTRY PROD YEAR SALES -------------------- --------------- ---------- ---------- Italy Bounce 2005 6300,19 Italy Mouse Pad 2005 6172,27 Italy Y Box 2005 105569,815 Zastosowanie FOR: RULES ( sales['mouse Pad', 2005] = 1.3 * sales['mouse Pad', 2001], sales['bounce', 2005] = 1.3 * sales['bounce', 2001], sales['y Box', 2005] = 1.3 * sales['y Box', 2001] ) RULES ( sales[for prod in ('Mouse Pad', 'Bounce', 'Y Box'), 2005] = 1.3 * sales[cv(prod), 2001] )
Weryfikacja istnienia Możliwe jest sprawdzenie, czy wiersz określony przez odwołanie komórki istniał przed wykonaniem klauzuli Model: sales[for month FROM 1 TO 3 INCREMENT 1, 2013] = CASE WHEN sales[currentv(), 2012] IS PRESENT THEN sales[currentv(), 2012] * 2 ELSE 0 END
Weryfikacja istnienia Dostępne są dwa inne sposoby weryfikacji istnienia wiersza. Wiersz istnieje (zwracane wyr2) lub nie istnieje (zwracane wyr3) sales[for month FROM 1 TO 3 INCREMENT 1, 2013] = PRESENTV(sales[CURRENTV(), 2012], sales[currentv(), 2012] * 2, 0) Wiersz istnieje, a komórka nie jest NULL (zwracane wyr2) lub wiersz nie istnieje (zwracane wyr3) sales[for month FROM 1 TO 3 INCREMENT 1, 2013] = PRESENTNNV(sales[CURRENTV(), 2012], sales[currentv(), 2012] * 2, 0)
Przykład 5 Kwestia opcji: KEEP NAV i IGNORE NAV. Która jest domyślna? Czy zmiana opcji spowoduje efekt? SELECT prod, year, growth, to_char(pct*100,'990.99') ' %' AS pct FROM sales_view WHERE lower(prod) LIKE '%phone%' MODEL RETURN UPDATED ROWS PARTITION BY (prod) DIMENSION BY (country, year) MEASURES (sale sales, 0 growth, 0 pct) (growth['spain', year>1999] = sales[cv(),cv()] Sales[CV(),CV()-1], pct['spain', year>1999] = round(( sales[cv(),cv()] sales[cv(),cv()-1] ) / sales[cv(),cv()-1],2) ) ORDER BY prod, year;
Przykład 5 PROD YEAR GROWTH PCT -------------------------------------------------- ---------- ---------- --------- Model C93822D Wireless Phone Battery 2000-197,67-17.00 % Model C93822D Wireless Phone Battery 2001 474,42 49.00 % Model C9827B Cordless Phone Battery 2000-229,37-10.00 % Model C9827B Cordless Phone Battery 2001 797,08 40.00 % Model K3822L Cordless Phone Battery 2000-376,07-21.00 % Model K3822L Cordless Phone Battery 2001 682,55 49.00 % Model K8822S Cordless Phone Battery 2000-443,43-14.00 % Model K8822S Cordless Phone Battery 2001 1386,52 51.00 % S27273M Extended Use w/l Phone Batt. 2000 2153,53 110.00 % S27273M Extended Use w/l Phone Batt. 2001 541,59 13.00 %
Przykład 5 Kwestia opcji: KEEP NAV i IGNORE NAV. A gdy zmienimy zakres wymiaru? SELECT prod, year, growth, to_char(pct*100,'990.99') ' %' AS pct FROM sales_view WHERE lower(prod) LIKE '%phone%' MODEL RETURN UPDATED ROWS PARTITION BY (prod) DIMENSION BY (country, year) MEASURES (sale sales, 0 growth, 0 pct) (growth['spain', year IS ANY] = sales[cv(),cv()] Sales[CV(),CV()-1], pct['spain', year IS ANY] = round(( sales[cv(),cv()] sales[cv(),cv()-1] ) / sales[cv(),cv()-1],2) ) ORDER BY prod, year;
Przykład 5 PROD YEAR GROWTH PCT -------------------------------------------------- ---------- ---------- -------- Model C93822D Wireless Phone Battery 1999 % Model C93822D Wireless Phone Battery 2000-197,67-17.00 % Model C93822D Wireless Phone Battery 2001 474,42 49.00 % Model C9827B Cordless Phone Battery 1998 % Model C9827B Cordless Phone Battery 1999 886,65 67.00 % Model C9827B Cordless Phone Battery 2000-229,37-10.00 % Model C9827B Cordless Phone Battery 2001 797,08 40.00 % Model K3822L Cordless Phone Battery 1998 % Model K3822L Cordless Phone Battery 1999 528,82 43.00 % Model K3822L Cordless Phone Battery 2000-376,07-21.00 % Model K3822L Cordless Phone Battery 2001 682,55 49.00 % Model K8822S Cordless Phone Battery 1998 % Model K8822S Cordless Phone Battery 1999 1867,39 ###### % Model K8822S Cordless Phone Battery 2000-443,43-14.00 % Model K8822S Cordless Phone Battery 2001 1386,52 51.00 % S27273M Extended Use w/l Phone Batt. 1999 % S27273M Extended Use w/l Phone Batt. 2000 2153,53 ###### % S27273M Extended Use w/l Phone Batt. 2001 541,59 13.00 %
Przykład 5 Kwestia opcji: KEEP NAV i IGNORE NAV. Przy dowolnym roku, zmiana na IGNORE NAV spowoduje... SELECT prod, year, growth, to_char(pct*100,'990.99') ' %' AS pct FROM sales_view WHERE lower(prod) LIKE '%phone%' MODEL RETURN UPDATED ROWS PARTITION BY (prod) DIMENSION BY (country, year) MEASURES (sale sales, 0 growth, 0 pct) IGNORE NAV (growth['spain', year IS ANY] = sales[cv(),cv()] Sales[CV(),CV()-1], pct['spain', year IS ANY] = round(( sales[cv(),cv()] sales[cv(),cv()-1] ) / sales[cv(),cv()-1],2) ) ORDER BY prod, year;
Przykład 5 sales[cv(),cv()-1] ) / sales[cv(),cv()-1],2) ) * BŁĄD w linii 13: ORA-01476: dzielnik jest równy zero
Przykład 5 Kwestia opcji: KEEP NAV i IGNORE NAV. Rozwiązaniem jest... SELECT prod, year, growth, to_char(pct*100,'990.99') ' %' AS pct FROM sales_view WHERE lower(prod) LIKE '%phone%' MODEL RETURN UPDATED ROWS PARTITION BY (prod) DIMENSION BY (country, year) MEASURES (sale sales, 0 growth, 0 pct) IGNORE NAV (growth['spain', year IS ANY] = sales[cv(),cv()] Sales[CV(),CV()-1], pct['spain', year IS ANY] = PRESENTV(sales[CV(),CV()-1], round(( sales[cv(),cv()] sales[cv(),cv()-1] ) / sales[cv(),cv()-1],2),1)) ORDER BY prod, year;
Przykład 5 PROD YEAR GROWTH PCT -------------------------------------------------- ---------- ---------- -------- Model C93822D Wireless Phone Battery 1999 1162,35 100.00 % Model C93822D Wireless Phone Battery 2000-197,67-17.00 % Model C93822D Wireless Phone Battery 2001 474,42 49.00 % Model C9827B Cordless Phone Battery 1998 1321,05 100.00 % Model C9827B Cordless Phone Battery 1999 886,65 67.00 % Model C9827B Cordless Phone Battery 2000-229,37-10.00 % Model C9827B Cordless Phone Battery 2001 797,08 40.00 % Model K3822L Cordless Phone Battery 1998 1239,69 100.00 % Model K3822L Cordless Phone Battery 1999 528,82 43.00 % Model K3822L Cordless Phone Battery 2000-376,07-21.00 % Model K3822L Cordless Phone Battery 2001 682,55 49.00 % Model K8822S Cordless Phone Battery 1998 1320,99 100.00 % Model K8822S Cordless Phone Battery 1999 1867,39 141.00 % Model K8822S Cordless Phone Battery 2000-443,43-14.00 % Model K8822S Cordless Phone Battery 2001 1386,52 51.00 % S27273M Extended Use w/l Phone Batt. 1999 1963,75 100.00 % S27273M Extended Use w/l Phone Batt. 2000 2153,53 110.00 % S27273M Extended Use w/l Phone Batt. 2001 541,59 13.00 %
Reference Models Klauzula Model może obsługiwać modele referencyjne. Są to zmaterializowane zapytania, które podlegają tylko odczytowi (nie są dla nich generowane nowe dane). MODEL [<reference models>] [MAIN <main-name>] [PARTITION BY (<cols>)] DIMENSION BY (<cols>) MEASURES (<cols>) Wykorzystywane są w modelu głównym (Main Model) jako tabele słownikowe.
Reference Models SELECT country, year, sales, dollar_sales FROM sales_view GROUP BY country, year MODEL REFERENCE conv_ref ON (SELECT country, exchange_rate FROM dollar_conv_tbl) DIMENSION BY (country) MEASURES (exchange_rate) IGNORE NAV MAIN conversion RULES DIMENSION BY (country, year) MEASURES (SUM(sale) sales, SUM(sale) dollar_sales) IGNORE NAV (dollar_sales['france', 2003] = sales[cv(country), 2002] * 1.02 * conv_ref.exchange_rate['france'], dollar_sales['poland', 2003] = sales['poland', 2002] * 1.05 * exchange_rate['poland']);
Klauzula Model a dane z CSV Klauzula Model może pracować na plikach tekstowych. Plik musi zostać wcześniej podłączony do bazy, za pomocą rozszerzenia external table. Dalsze operacje nie różnią się od przypadku, gdy tabela jest składowana w bazie
Klauzula Model a dane z CSV CREATE TABLE sprzedaz2011 ( id NUMBER(4), kwartal NUMBER(2), kategoria VARCHAR2(15), ilosc NUMBER(4) ) ORGANIZATION EXTERNAL (TYPE ORACLE_LOADER DEFAULT DIRECTORY data_imp ACCESS PARAMETERS (RECORDS DELIMITED BY NEWLINE BADFILE 'bad' LOGFILE 'log' SKIP 1 FIELDS TERMINATED BY ';' ( id,kwartal,kategoria,ilosc) ) LOCATION ('sprzedaz2011.csv') );
Klauzula Model a dane z CSV SELECT kwartal, kategoria, to_char(ile,'999.99') ile FROM sprzedaz2011 MODEL RETURN UPDATED ROWS PARTITION BY (kwartal) DIMENSION BY (kategoria) MEASURES (ilosc ile) RULES ( ile[kategoria IS ANY] = ile[cv()]*1.25 ) ORDER BY kwartal, kategoria ;
Klauzula Model a dane z CSV KWARTAL KATEGORIA TO_CHAR ---------- --------------- ------- 1 RTV 187.50 1 AGD 125.00 1 komputery 162.50 1 telefony 312.50 2 RTV 187.50 2 AGD 137.50 2 komputery 150.00 2 telefony 375.00 4 RTV 237.50 4 AGD 175.00 4 komputery 187.50 4 telefony 375.00 3 RTV 225.00 3 AGD 112.50 3 komputery 150.00 3 telefony 412.50
Klauzula Model a dane z CSV KWARTAL KATEGORIA ILE ---------- --------------- ------- 1 AGD 125.00 1 komputery 162.50 1 RTV 187.50 1 telefony 312.50 2 AGD 137.50 2 komputery 150.00 2 RTV 187.50 2 telefony 375.00 3 AGD 112.50 3 komputery 150.00 3 RTV 225.00 3 telefony 412.50 4 AGD 175.00 4 komputery 187.50 4 RTV 237.50 4 telefony 375.00
Typowe problemy Umieszczenie na liście SELECT kolumny niedozwolonej (nie będącej partycją, wymiarem lub miarą): ORA-32614: niedozwolone wyrażenie MODEL SELECT Podanie klauzuli ORDER BY przed MODEL: ORA-00933: polecenie SQL niepoprawnie zakończone
Podsumowanie Zasady użycia: Miejsce w składni SELECT Mapowanie kolumn Korzyści Wydajność Skalowalność Zarządzanie Funkcjonalności Aktualizacja i/lub generowanie nowych danych Tworzenie reguł z uwzględnieniem kolejności realizacji Obsługa pętli Możliwość ograniczenia prezentowanych wyników
Dziękuję za uwagę Zapraszamy wszystkich uczestników na szkolenie Język SQL dla analityków danych w specjalnej cenie zamiast 1500 840 PLN Terminy: 2012-05-28 2012-05-30 Wrocław 2012-05-30 2012-06-01 Warszawa 2012-06-11 2012-06-13 - Kraków