590 likes | 762 Views
Il linguaggio MDX. Il linguaggio MDX ( M ulti D imensional e X pression) è usato per recuperare e manipolare dati multidimensionali in SQL Server Analysis Services , quali i dati archiviati in cubi
E N D
Il linguaggio MDX • Il linguaggio MDX (MultiDimensional eXpression) è usato per recuperare e manipolare dati multidimensionali in SQL Server Analysis Services, quali i dati archiviati in cubi • Come una query SQL, ogni query MDX comporta una richiesta di dati (la clausola SELECT), un'origine (la clausola FROM) e un filtro (la clausola WHERE): estrazione di parti specifiche di dati da un cubo per l'analisi. • MDX ha una sintassi simile a SQL ma la semantica è diversa • In alcuni aspetti è molto verboso e ridondante tuttavia, è possibile omettere nelle espressioni alcune parti significative, la cui interpretazione è basata su regole di default • MDX non è un linguaggio di interrogazione in senso stretto : permette di calcolare, a partire da un cubo, un dataset che ha una struttura simile a un cubo • tuttavia, il risultato di una interrogazione non è un cubo • MDX non è un linguaggio chiuso • MDX non può essere usato per la definizione di viste
livelli dimensione STORE (ALL) STORE CITY STATE COUNTRY (ALL) Ditutto RE EmiliaR Italia ALL membri NonSoloX RE EmiliaR Italia ALL NonSoloY MO EmiliaR Italia ALL NonSoloZ RM Lazio Italia ALL ... ... ... ... ALL Schemi multi-dimensionali in Analysis Services • Dimensioni e attributi dimensionali si chiamano livelli • I valori delle dimensioni e degli attributi dimensionali si dicono membri • Per denotare un membro (le [ ] sono facoltative) : • [STORE].[ALL].[Italia].[EmiliaR].[RE] : percorso completo • [STORE].[RE] : se il membro “RE” è univoco nella dimensione STORE • [CITY].[RE] : se il livello CITY è univoco in tutte le dimensioni del cubo
Eventi e aggregazione: tuple • Una tupla è una ennupla di membri denotati tra parentesi () • Una tupla costituita da un membro per ciascuna dimensione individua un evento primario: ([data].[15/5/2004],[prodotto].[brillo], [store].[DiTutto]) In altri termini è una tupla corrispondente al pattern primario. • Un evento secondario è individuato da una tupla corrispondente ad un pattern secondario • ([data].[15/5/2004],[prodotto].[brillo]) corrisponde al Pattern {Data,Prodotto} • ([mese].[5/2004],[prodotto].[brillo], [store].[DiTutto]) corrisponde al Pattern {Mese,Prodotto,Store} • ([mese].[5/2004],[prodotto].[brillo],[City].[RE]) corrisponde al Pattern {Mese,Prodotto,City} • MDX usa il concetto di tupla anche per estrarne i valori delle misure. • ([data].[15/5/2004],[prodotto].[brillo], [store].[DiTutto], Measures.[incasso]) il valore della misura Incasso è riferito all’evento primario • ([mese].[5/2004],[prodotto].[brillo], [store].[DiTutto], Measures.[incasso]) il valore della misura Incasso è riferito all’evento secondario, ovvero è calcolato dopo aver aggregato su mese
negozio 10 BigWare parte vite data 10-10-2001 Il cubo delle vendite • Tupla MDX per identificare l’evento primario:(data.[10-10-2001], parte.[vite], negozio.[BigWare]) • Tupla MDX per identificare l’evento primario e estrarre Incasso:(data.[10-10-2001], parte.[vite], negozio.[BigWare],Measures.[Incasso])
negozio 10 BigWare parte data vite 10-10-2001 MDX: istruzione SELECT • L’istruzione SELECT di MDX consente di selezionare i dati da un cubo • Una prima possibilità per selezionare la cella in figura ed elencarne la misura Incasso è tramite la seguentequery MDX: SELECT Measures.[Incasso] FROM CuboVendite WHERE (data.[10-10-2001], parte.[vite], negozio.[BigWare]) • In effetti Measures.[Incasso] deve essere Measures.[Incasso] ON AXIS(0)
Struttura delle interrogazioni MDX • Nella versione più semplice, la struttura delle interrogazioni MDX è:SELECT specifica_asse {, specifica_asse} FROM nome_cubo WHERE specifica_slicer • gli assi sono le “dimensioni” del risultato ovvero, gli elementi che devono comporre l’intestazione del risultato - Ogni asse specifica un insieme di tuple • lo slicer contiene le condizioni di selezione • Il risultato di una interrogazione è una struttura multidimensionale, chiamata dataset, è organizzata mediante uno o più assi, detti, in ordine, COLUMNS, ROWS, PAGES, SECTIONS e CHAPTERS - oppure AXIS(0), AXIS(1), AXIS(2), ...
negozio 10 BigWare parte data vite 10-10-2001 Cubi in MDX : Dataset • Così come l’istruzione SELECT in SQL restituisce una tabella, l’istruzione SELECT in MDX restituisce un cubo (dataset) • Un’altra possibilità per selezionare la cella in figura è quella di costruire un nuovo dataset costituito dalla sola cella • Il nuovo dataset ha tre dimensioni : AXIS(0), AXIS(1) e AXIS(2) • Non avendo posto nessuna condizione sulle Measures in tale dataset ci saranno tutte le misure SELECT { (data.[10-10-2001]) } ON AXIS(0), { (parte.[vite]) } ON AXIS(1), {(negozio.[BigWare]) } ON AXIS(2) FROM CuboVendite
negozio 30 10 BigWare parte vite ’15/4/2001' '5/4/2001' data Per selezionare più celle • Si può costruire il dataset formato dalle due celle tramite la query: SELECT { ([data].[5/4/2001]), ([data].[15/4/2001]) } ON AXIS(0), { ([parte].[vite]) } ON AXIS(1), { ([negozio].[BigWare]) } ON AXIS(2) FROM CuboVendite • Non si può ottenere l’incasso complessivo nelle due date di Vite in BigWare:Servirebbe una condizione WHERE con OR:([data].[5/4/2001]) OR ([data].[15/4/2001]) ma questo non è consentito in MDX! • Per ottenere l’incasso complessivo occorrerà usare un membro calcolato.
negozio 'DiTutto' prodotto data MDX: Slicing • Fissando il valore per una dimensione (ad esempio, per Negozio) siottiene un dataset bidimensionale • Sulle altre dimensioni (esempio Data) devo riportare tutti i valori assunti da tale dimensione, ovvero tutti i membri della dimensione: [data].MEMBERS SELECT data.MEMBERS ON AXIS(0), prodotto.MEMBERS ON AXIS(1) FROM CuboVendite WHERE (negozio.[DiTutto]) • Il precedente dataset si può ancora considerare cometridimensionale, ma con unadimensione che assume un unico valore: SELECT data.MEMBERS ON AXIS(0), prodotto.MEMBERS ON AXIS(1), {(negozio.[DiTutto]) } ON AXIS(2) FROM CuboVendite
negozio 'DiTutto' prodotto data '5/4/2001' MDX: Slicing • Fissando il valore per due dimensioni si ha un dataset unidimensionale SELECT prodotto.MEMBERS ON AXIS(1) FROM CuboVendite WHERE (negozio.[DiTutto], data.[5/4/2001] ) • Il precedente dataset si può ancora considerare cometridimensionale, ma con duedimensioni che assumonoun unico valore: SELECT {(data.[5/4/2001])} ON AXIS(0), prodotto.MEMBERS ON AXIS(1), {(negozio.[DiTutto]) } ON AXIS(2) FROM CuboVendite
tipo città mese S tipo negozio mese S parte data Aggregazione
città 42 tipo RE Frutta mese Marzo MDX: Aggregazione Tupla MDX per identificare l’evento secondario • Query MDX per selezionare la misura Incasso: ([data].[mese].[Marzo], [parte].[tipo].[Frutta], [negozio].[citta].[RE]) SELECT Measures.[Incasso] FROM CuboVendite WHERE([data].[mese].[Marzo], [parte].[tipo].[Frutta], negozio.[citta].[RE]) • Il valore restituito è calcolato sulla base degli operatori di aggregazione
città 42 tipo RE Frutta mese Marzo MDX: Aggregazione • Anche nel caso dell’aggregazione, è possibile selezionare la macro-cellacostruendo un nuovo dataset costituito dalla sola cella : SELECT { ([data].[mese].[Marzo])} ON AXIS(0), { ([parte].[tipo].[Frutta]) } ON AXIS(1), { ([negozio].[citta].[RE]) } ON AXIS(2) FROM CuboVendite • Il valore associato alla macro-cella è calcolato sulla base degli operatori di aggregazione
città 42 58 tipo RE Frutta mese Marzo Aprile MDX: Aggregazione • Si può costruire il dataset formato dalle due macro-celle tramite la query: SELECT { ([data].[mese].[Marzo]), [data].[mese].[Aprile]} ON AXIS(0), { ([parte].[tipo].[Frutta]) } ON AXIS(1), { ([negozio].[citta].[RE]) } ON AXIS(2) FROM CuboVendite • Come nel caso di singole celle, non è possibile ottenere l’incasso complessivodei due mesi: occorrerà anche in questo caso definire (nella query MDX) un membro calcolato.
città tipo mese MDX: Aggregazione • Sul secondo asse devo riportare tutti i valori assunti da tipo, ovvero tutti i membri del livello tipo: [parte].[tipo].MEMBERS • Come ottenere tutte le macro-celle dell’aggregazione? SELECT [data].[mese].MEMBERS ON AXIS(0), [parte].[tipo].MEMBERS ON AXIS(1), [negozio].[citta].MEMBERS ON AXIS(2) FROM CuboVendite • Si noti che la funzione MEMBERS costruisce un insieme quindi è inutile usare le { … } nella costruzione degli assi
città città tipo mese Bevanda mese MDX: Aggregazione e Slicing SELECT [data].[mese].MEMBERS ON AXIS(0), [negozio].[citta].MEMBERS ON AXIS(1) FROM CuboVendite WHERE ([parte].[tipo].[Bevanda]) • Dataset bidimensionale, ottenuto fissando il valore ad una dimensione: • Dataset tridimensionale, in cui una dimensione assume un solo valore: SELECT [data].[mese].MEMBERS ON AXIS(0), { ([parte].[tipo].[Bevanda]) } ON AXIS(1), [negozio].[citta].MEMBERS ON AXIS(2) FROM CuboVendite
città città mese tipo mese MDX non è un linguaggio chiuso • Non si può creare una vista ed interrogarla! CREATE VIEW PROVA(mese,tipoparte,cittaneg) AS SELECT data.[mese].MEMBERS ON AXIS(0), parte.[tipo].MEMBERS ON AXIS(1), negozio.[citta].MEMBERS ON AXIS(2) FROM CuboVendite SELECT mese.MEMBERS ON AXIS(0), cittaneg.MEMBERS ON AXIS(1) FROM PROVA WHERE (tipoparte.[Bevanda])
Dove e come utilizzare MDX? • Dove e come utilizziamo SQL? • Esecuzione interattiva di interrogazioni (es SQL Query Analyzer) • Interrogazioni incorporate in un’applicazione client: Import/export dati in DTS applicazioni che accedono tramite ODBC • embedded SQL • Il linguaggio MDX è usato (ad oggi) solo in contesti specifici • MDX Sample Application: applicazione per l’esecuzione interattiva di interrogazioni MDX con risultati bidimensionali • Interrogazioni MDX incorporate in un’applicazione client:“Office OLAP Components”, quali “Pivot Table Service” “Excel Pivot Table”
negozio 30 10 BigWare parte vite ’15/4/2001' '5/4/2001' data MDX Sample Application - MDX SA • Si consideri il seguente cubo e la seguete query MDX: SELECT { (data.[5/4/2001]), (data.[15/4/2001]) } ON AXIS(0), { (parte.[vite]) } ON AXIS(1), {(negozio.[BigWare]) } ON AXIS(2) FROM CuboVendite • Come visualizzarlo in modo bidimensionale con MDX SA? SELECT {(negozio.[BigWare]) } ON COLUMNS, { (parte.[vite],data.[5/4/2001]), (parte.[vite],data.[15/4/2001]) } ON ROWS FROM CuboVendite
Cubo Sales (database FoodMart) • dimensione Time; livelli Year, Quarter, Month • dimensione Product; livelli (All), Product Family, Product Department, Product Category, Product Subcategory, Brand Name, Product Name • dimensione Store; livelli (All), Store Country, Store State, Store City, Store Name • dimensione Customers; livelli (All), Country, State Province, City, Name • dimensione Education Level; livelli (All), Education Level • dimensione Gender; livelli (All), Gender • dimensione Marital Status; livelli (All), Marital Status • dimensione Yearly Income; livelli (All), Yearly Income • dimensione Promotion Media; livelli (All), Media Type • dimensione Promotions; livelli (All), Promotion Name • misure (Measures); membri Unit Sales, Store Cost, Store Sales, Sales Count, Store Sales Net
Esempio di interrogazione MDX • Totale delle unità di vendita vendute raggruppate per anno SELECT {([Measures].[Unit Sales])} ON COLUMNS, {([Time].[Year].MEMBERS)} ON ROWS FROM [Sales] • Esecuzione dell’interrogazione in MDX SA
Operatore punto L’operatore punto . è usato • per accedere a un livello di una dimensione : [Time].[Year] • per accedere a un membro di una dimensione : [Time].[1997] • per eseguire una operazione: [Time].[Year].MEMBERS è una espressione che restituisce l’insieme dei membri del livello [Time].[Year] • Esempio : calcolare il totale di ogni misura raggruppato per anno SELECT {([Measures].MEMBERS)} ON COLUMNS, {([Time].[Year].MEMBERS)} ON ROWS FROM [Sales]
Tuple e dimensionalità • Una tupla può includere sia membri di più dimensioni ([Time].[1997],[Store].[Canada]) sia più membri di una stessa dimensione. ([Time].[1997], [Time].[1997].[Q1]) • Il termine dimensionalità viene utilizzato per indicare le dimensioni descritte dai membri di una tupla. • Le seguenti due tuple hanno la stessa dimensionalità • ([Time].[1997],[Store].[Canada]) • ([Time].[1997],[Store].[USA]) • Le seguenti due tuple non hanno la stessa dimensionalità • ([Time].[1997],[Store].[Canada]) • ([Store].[USA],[Time].[1997])
Set di tuple Un set è un insieme ordinato di zero, una o più tuple. • I set si denotano tramite parentesi graffe { … } : {([Time].[1997],[Store].[Canada]),([Time].[1997], [Store].[USA])} • Il set può essere calcolato: {([Time].[Year].MEMBERS)}In tal caso non è necessario introdurre le { … } Set e dimensionalità • Le tuple all'interno di un set devono avere la stessa dimensionalità: {([Time].[1997]),([Time].[1997].[Q1])} {([Time].[1997],[Store].[Canada])([Time].[1997],[Store].[USA])} • Le seguenti espressioni non sono corrette: {([Time].[1997]), [Store].[Canada])} {([Time].[1997],[Store].[Canada])([Store].[USA],[Time].[1997])}
Specifica degli assi La specifica di un asse è una espressione che descrive un set di tuple • Esempio: Calcolare i totali delle vendite (di ogni misura) nel 1997 SELECT {([Measures].MEMBERS)} ON COLUMNS, {([Time].[1997])} ON ROWS FROM [Sales] • Esempio: Calcolare i totali delle vendite (di ogni misura) nel 1997 e nel primo trimestre 1997 SELECT {([Measures].MEMBERS)} ON COLUMNS, {([Time].[1997]), ([Time].[1997].[Q1])} ON ROWS FROM [Sales]
Specifica degli assi • Esempio: Calcolare i totali delle vendite (di ogni misura) nel 1997 e nel 1998 per il Canada e gli Stati Uniti: SELECT {([Measures].MEMBERS)} ON COLUMNS, {([Time].[1997], [Store].[Canada]), ([Time].[1997], [Store].[USA]), ([Time].[1998], [Store].[Canada]), ([Time].[1998], [Store].[USA])} ON ROWS FROM [Sales] • L'ordine delle tuple in un set ha effetto sull'ordine di nidificazione in una dimensione dell'asse. • Scambiando l’ordine si ottiene
CROSSJOIN L’operatore di CROSSJOIN consente la specifica di un asse come prodotto cartesiano di due (o più ... ) insiemi • Esempio, se si vogliono raggruppare dei dati su un asse per anno e nazione, per tutti gli anni e per il Canada e gli USA SELECT {([Measures].MEMBERS)} ON COLUMNS, CROSSJOIN({[Time].[Year].MEMBERS}, {[Store].[Canada], [Store].[USA]})ON ROWS FROM [Sales]
NONEMPTYCROSSJOIN • L’operatore di NONEMPTYCROSSJOIN equivale al CROSSJOIN ma visualizza soltanto le righe contenenti celle non vuote • Il CROSSJOIN con più di due insiemi non può essere eseguito in MDX Sample Application (la loro visualizzazione risulterebbe problematica ...): si deve usare NONEMPTYCROSSJOIN • Ad esempio, se si vogliono raggruppare dei dati su un asse per anno, nazione e sesso, per tutti gli anni e per il Canada e gli USA SELECT {([Measures].MEMBERS)} ON COLUMNS, NONEMPTYCROSSJOIN({[Time].[Year].MEMBERS}, {[Store].[Canada],[Store].[USA]}, [Gender].Members)ON ROWS FROM [Sales]
MDX: PRINCIPALI OPERATORI • x.MEMBERS : insieme dei membri della dimensione o livello x • m.CHILDREN : insieme dei figli del membro m • Esempio: Calcolare i totali di ogni misura per ogni stato degli USA SELECT {([Measures].MEMBERS)} ON COLUMNS, {([Store].[USA].CHILDREN)} ON ROWS FROM [Sales] • DESCENDANTS(m,l) : insieme dei discendenti del membro m al livello l • Esempio: Calcolare i totali di ogni misura per ogni città degli USA SELECT {([Measures].MEMBERS)} ON COLUMNS, DESCENDANTS([Store].[USA], [Store City]) ON ROWS FROM [Sales]
MDX: la clausola di selezione WHERE • La clausola WHERE specifica condizioni di selezione dell’interrogazione • la condizione di selezione assume solitamente la forma di una congiunzione di uguaglianze, espresse tramite una tupla • Esempio: calcolare il totale delle unità vendute per anno, limitatamente alle vendite negli USA SELECT {([Measures].[Unit Sales])} ON COLUMNS, [Time].[Year].MEMBERS ON ROWS FROM [Sales] WHERE ([Store].[Store Country].[USA]) • Esempio: calcolare il totale delle unità vendute per anno, limitatamente alle vendite effettuate negli USA dagli uomini SELECT {([Measures].[Unit Sales])} ON COLUMNS, [Time].[Year].MEMBERS ON ROWS FROM [Sales] WHERE ([Store].[Store Country].[USA], [Gender].[M])
MDX: la clausola di selezione WHERE • Una condizione di selezione nel WHERE non può essere relativa a una dimensione usata nella specifica di un asse • Esempio: calcolo unità vendute per trimestre, limitatamente al 1997 • la seguente interrogazione non è corretta SELECT {([Measures].[Unit Sales])} ON COLUMNS, {([Time].[Quarter].MEMBERS)} ON ROWS FROM [Sales] WHERE ( [Time].[Year].[1997]) • per esprimere i trimestri del 1997 occorre usare DESCENDANT SELECT {([Measures].[Unit Sales])} ON COLUMNS, DESCENDANTS ([Time].[1997], [Quarter]) ON ROWS FROM [Sales]
MDX: la clausola di selezione WHERE • Una condizione di selezione non può vincolare una stessa dimensione a più membri • Ad esempio, la seguente interrogazione non è corretta SELECT {([Measures].[Unit Sales])} ON COLUMNS, {([Time].[Year].MEMBERS)} ON ROWS FROM [Sales] WHERE ([Store].[Store Country].[USA], [Store].[Store Country].[Canada]) • per considerare le vendite complessive degli USA e del Canada bisogna usare i membri calcolati (vedi più avanti)
INTERPRETAZIONI DI DEFAULT: misure • le misure sono membri di Measures: la prima è [Unit Sales] SELECT {([Store].[USA].CHILDREN)} ON COLUMNS, {([Time].[Year].MEMBERS)} ON ROWS FROM [Sales] • questa interrogazione è equivalente alla seguente SELECT {([Store].[USA].CHILDREN)} ON COLUMNS, {([Time].[Year].MEMBERS)} ON ROWS FROM [Sales] WHERE ([Measures].[Unit Sales]) • In questa interrogazione l’aggregazione viene calcolata • rispetto alla misura specificata nella condizione di selezione • usando la funzione di aggregazione associata per default (nella definizione del cubo) alla misura selezionata
Membri calcolati • In una interrogazione MDX si possono definire nuovimembri calcolati con lo stesso significato e semantica dei membri calcolati in Analysis Services • essi sono utili per definire nuove misure che servono solo all’interno della specifica interrogazione • sintassi delle interrogazioni con la definizione di membri calcolati WITH MEMBER specifica_membro {MEMBER specifica_membro} SELECT .... • Esempio calcolare il profitto per anno per categoria di prodotto WITH MEMBER [Measures].[Store Profit] AS '[Measures].[Store Sales] - [Measures].[Store Cost]' SELECT {([Time].[Year].MEMBERS)} ON COLUMNS, {([Product].[Product Category].MEMBERS)} ON ROWS FROM [Sales] WHERE ([Measures].[Store Profit])
Membri calcolati :esempi • Calcolare il profitto per categoria di prodotto, per l’anno 1997 WITH MEMBER [Measures].[Store Profit] AS '[Measures].[Store Sales] - [Measures].[Store Cost]' SELECT {([Measures].[Store Profit])} ON COLUMNS, {([Product].[Product Category].MEMBERS)} ON ROWS FROM [Sales] WHERE ([Time].[Year].[1997]) WITH MEMBER [Measures].[Store Profit] AS '([Time].[Year].[1997], [Measures].[Store Sales]) - ([Time].[Year].[1997], [Measures].[Store Cost])' SELECT {([Measures].[Store Profit])} ON COLUMNS, {([Product].[Product Category].MEMBERS)} ON ROWS FROM [Sales]
Membri calcolati : esempi I membri calcolati possono essere usati come i membri “ordinari” WITH MEMBER [Measures].[Store Profit] AS '[Measures].[Store Sales] - [Measures].[Store Cost]' MEMBER [Measures].[Store Percent Profit] AS '[Measures].[Store Profit] / [Measures].[Store Cost]' SELECT {([Measures].[Store Profit]), ([Measures].[Store Percent Profit])} ON COLUMNS, {([Product].[Product Category].MEMBERS)} ON ROWS FROM [Sales] WHERE ([Time].[Year].[1997])
Membri calcolati sulle dimensioni • In Analysis Service è possibile definire un membro calcolato sulla base dei valori delle misure in corrispondenza di due o più membri delle dimensioni • Inoltre si può scegliere a quale dimensione appartiene il nuovo membro calcolato, cioè non deve essere necessariamente un membro di Measures • Esempio: differenza dei valori assunti dalle misure in corrispondenza dei membri [Time].[1998] e [Time].[1997] : si definisce il membro calcolato[Time].[1998] - [Time].[1997]come appartenente alla dimensione [Time]
Membri calcolati sulle dimensioni in MDX • Si può definire un membro calcolato sulle dimensioni anche in una query MDX • Ad esempio, si può definire in MDX lo stesso membro calcolato precedente come membro nella dimensione Time per indicare “la differenza tra il 1998 e il 1997” • WITH MEMBER [Time].[1998 - 1997] AS '[Time].[1998] - [Time].[1997]' SELECT {([Time].[1997]), ([Time].[1998]), ([Time].[1998 - 1997])} ON COLUMNS, {([Product].[Product Family].MEMBERS)} ON ROWS FROM [Sales] WHERE ([Measures].[Unit Sales])
Membri calcolati : un esempio più complesso WITH MEMBER [Measures].[Store Profit] AS '[Measures].[Store Sales] - [Measures].[Store Cost]' MEMBER [Time].[1998 - 1997] AS '[Time].[1998] - [Time].[1997]' SELECT {([Measures].[Store Sales]), ([Measures].[Store Cost]), ([Measures].[Store Profit])} ON COLUMNS, {([Time].[1997]), ([Time].[1998]), ([Time].[1998 - 1997])} ON ROWS FROM [Sales]
Ordine di valutazione In presenza di più membri calcolati occorre considerare l’ordine di valutazione • Esempio: Rapporto del profitto tra i primi due trimestri del 1997 • calcolare prima i profitti dei due trimestri e poi il loro rapporto WITH MEMBER [Measures].[Store Profit] AS '[Measures].[Store Sales] - [Measures].[Store Cost]' MEMBER [Time].[1997].[Q1 / Q2] AS '[Time].[1997].Q1 / [Time].[1997].Q2' SELECT {([Measures].[Store Sales]), ([Measures].[Store Cost]), ([Measures].[Store Profit])} ON COLUMNS, {([Time].[1997].Q1), ([Time].[1997].Q2), ([Time].[1997].[Q1 / Q2])} ON ROWS FROM [Sales] Questa interrogazione non è corretta in quanto restituisce: Nota : le cifre decimali sono indicate in alcuni casi con la ‘,’ in altri con il ‘.’ Dipende dal sistema installato
Ordine di valutazione: SOLVE_ORDER Per calcolare prima i profitti dei due trimestri e poi il loro rapporto occorre stabilire esplicitamente l’ordine di valutazione tramite la clausola SOLVE_ORDER: il membro con SOLVE_ORDER più basso verrà calcolato per prima WITH MEMBER [Measures].[Store Profit] AS '[Measures].[Store Sales] - [Measures].[Store Cost]', SOLVE_ORDER = 0 MEMBER [Time].[1997].[Q1 / Q2] AS '[Time].[1997].Q1 / [Time].[1997].Q2', SOLVE_ORDER = 1 SELECT … come prima In assenza di SOLVE_ORDER si seguono ordini di valutazione prestabiliti Nella definizione dei cubi: è sempre opportuno indicarlo esplicitamente.
Ordine di valutazione : membri addittivi L’ordine di valutazione è irrilevante per membri addittivi • Esempio: Differenza del profitto tra i primi due trimestri del 1997 WITH MEMBER [Measures].[Store Profit] AS '[Measures].[Store Sales] - [Measures].[Store Cost]’, SOLVE_ORDER = 0 MEMBER [Time].[1997].[Q1 – Q2] AS '[Time].[1997].Q1 - [Time].[1997].Q2’, SOLVE_ORDER = 1 SELECT {([Measures].[Store Sales]), ([Measures].[Store Cost]), ([Measures].[Store Profit])} ON COLUMNS, {([Time].[1997].Q1), ([Time].[1997].Q2),([Time].[1997].[Q1 – Q2])} ON ROWS FROM [Sales] Lo stesso risultato si ottiene invertendo l’ordine di valutazione!
Funzioni Numeriche Sono funzioni (SUM,MAX,MIN, ..) applicate solitamente alle misure • SUM(«Set», «Expression») • Calcola la somma di «Expression» su «Set» • Esempio: per ogni trimestre del 1997, totale delle vendite per gli stati OR e WA WITH MEMBER [Store].[OR + WA] AS 'SUM({[Store].[USA].[OR],[Store].[USA].[WA]}, [Measures].[Store Sales])' SELECT {([Store].[USA].[OR]), ([Store].[USA].[WA]), ([Store].[OR + WA])} ON COLUMNS, {([Time].[1997].CHILDREN)} ON ROWS FROM [Sales] WHERE ([Measures].[Store Sales])
Funzioni Numeriche L’insieme considerato nel calcolo delle funzioni numeriche è implicitamente vincolato alle altre dimensioni usate nella interrogazione SELECT {([Measures].[Store Sales]) } ON COLUMNS, {([Store].[USA].CHILDREN)} ON ROWS FROM [Sales] WITH MEMBER [Measures].[Max1] AS 'MAX({[Store].[USA].CHILDREN},[Measures].[Store Sales])' SELECT {([Measures].[Max1] ) } ON COLUMNS FROM [Sales] Se però aggiungo anche l’asse[Time].[1997].CHILDREN il massimo è riferito ai trimestri : WITH MEMBER [Measures].[Max1] AS 'MAX({[Store].[USA].CHILDREN},[Measures].[Store Sales])' SELECT [Time].[1997].CHILDREN ON COLUMNS, [Store].[USA].CHILDREN ON ROWS FROM [Sales] WHERE [Measures].[Max1]
Funzioni Numeriche : esempio Esempio: per ogni trimestre del 1997, e per ogni stato degli USA vendite e massimo delle vendite per gli stati degli USA WITH MEMBER [Measures].[Max STATE OF USA Store Sales] AS 'MAX({[Store].[USA].CHILDREN},[Measures].[Store Sales])' SELECT CROSSJOIN( {([Time].[1997].CHILDREN)}, {([Measures].[Store Sales]), ([Measures].[Max STATE OF USA Store Sales]) }) ON COLUMNS, {([Store].[USA].CHILDREN)} ON ROWS FROM [Sales]
Funzioni Numeriche : esempio Un membro calcolato può essere usato nella definizione di un altro membro calcolato Esempio: per ogni trimestre del 1997, e per ogni stato degli USA vendite, massimo delle vendite e differenza per gli stati degli USA WITH MEMBER [Measures].[Max STATE OF USA Store Sales] AS 'MAX({[Store].[USA].CHILDREN},[Measures].[Store Sales])' MEMBER [Measures].[Difference] AS '[Measures].[Max STATE OF USA Store Sales] - [Measures].[Store Sales]’ SELECT CROSSJOIN( {([Time].[1997].CHILDREN)}, {([Measures].[Store Sales]), ([Measures].[Max STATE OF USA Store Sales]), ([Measures].[Difference])}) ON COLUMNS {([Store].[USA].CHILDREN)} ON ROWS FROM [Sales]
Misure Migliori e peggiori : TopCount • TopCount(«Set», «Count», «Numeric Expression») • ordina un set in base al valore di «Numeric Expression» • e restituisce i primi «Count» membri, dove «Count» è un'espressione numerica. SELECT TOPCOUNT ( [Product].[Product Name].MEMBERS,5, ( [Measures].[Unit Sales],[TIME].[1997])) ON COLUMNS FROM SALES Le vendite ([Measures].[Unit Sales]) per i trimestridel 1997 dei 5 prodotti più venduti nel 1997 (cioè rispetto a [Measures].[Unit Sales]) SELECT { ([TIME].[1997].CHILDREN)} ON COLUMNS, TOPCOUNT ( [Product].[Product Name].MEMBERS,5,( [Measures].[Unit Sales],[TIME].[1997])) ON ROWS FROM SALES
Misure Migliori e peggiori : TopSum • TopSum(«Set», «Value», «Num. Expr») • ordina «Set» su «Num. Expr» e estrae i primi n (il più piccolo numero possibile) • elementi tali che la loro somma è almeno «Value». SELECT TOPSUM ( [Product].[Product Name].MEMBERS,1000, [Measures].[Unit Sales]) ON COLUMNS FROM SALES WITH MEMBER [MEASURES].[NULLO] AS ' NULL ' SELECT TOPSUM ( [Product].[Product Name].MEMBERS, 1000, [Measures].[Unit Sales] ) ON COLUMNS FROM SALES WHERE [MEASURES].[NULLO]
SELECT {([Store].[USA].CHILDREN)} ON COLUMNS, {([Time].[Year].MEMBERS)} ON ROWS FROM [Sales] SELECT {([Store].[USA].CHILDREN)} ON COLUMNS, NON EMPTY {([Time].[Year].MEMBERS)} ON ROWS FROM [Sales] Celle vuote • Le celle vuote sono presenti nelle istruzioni MDX quando i dati relativi all'intersezione di due o più dimensioni non esistono. • La funzione IsEmpty(<expression>) restituisce TRUE se <expression> è una cella vuota. In caso contrario, restituisce FALSE. • NON EMPTY : per non visualizzare le celle vuote • Quando il valore di cella vuota è un operando per uno degli operatori numerici (+, -, *, /), ha la stessa funzione del valore zero. Esempi WITH MEMBER [Time].[1997 - 1998] AS '[Time].[1998] - [Time].[1997]' SELECT {([Store].[USA].CHILDREN)} ON COLUMNS, NON EMPTY {([Time].[1997 - 1998])} ON ROWS FROM [Sales]
Operazioni sui membri • Alcune operatori consentono di accedere al membro “corrente” di una dimensione e ai membri vicini di un dato membro • x.CURRENTMEMBER • calcola il membro corrente della dimensione o livello x • m.PREVMEMBER e m.NEXTMEMBER • calcola il membro che precede (segue) il membro m nell’ambito dello stesso livello di m • Per il primo membro PREVMEMBER restituisce una cella vuota • Per l’ultimo membro NEXTMEMBER restituisce una cella vuota Esempio WITH MEMBER [Measures].[VENDITE TRIMESTRE PRECEDENTE] AS '([Measures].[Store Sales], [Time].PREVMEMBER)' SELECT { [Measures].[VENDITE TRIMESTRE PRECEDENTE]} ON COLUMNS, {([Time].[1997].CHILDREN)} ON ROWS FROM [Sales]