Esempio di progettazione di un DW! La sorgente dati è costituita da un unico DataBase SQL-Server con informazioni sui Manifesti degli Studi e gli orari delle lezioni. Viene considerato il progetto di un DataMart per l analisi dei crediti (CFU) e degli orari delle lezioni! Sommario 1. Analisi degli schemi e dei dati per definire lo schema riconciliato " Si discute quindi dove e come realizzare tale schema riconciliato con riferimento alle architetture a due e a tre livelli 2. Realizzazione del DB riconciliato : architetture a 3 e a 2 livelli 3. Punti caratteristici della costruzione dello schema di fatto relativo agli orari 4. Progetto logico e alimentazione 5. Esempi di cubi in Analysis Services 6. Esempi di interrogazioni in MDX 7. Esempi di Data Transformation Service (DTS) di SQL-SERVER " Questi esempi sono riferiti al caso dell alimentazione del Dbriconciliato con i dati del DB originale (vedi architettura a 3 livelli). Ovviamente i concetti introdotti si applicano anche ad altre situazioni (come ad esempio l alimentazione del DataWarehouse tramite il Dbriconciliato) 8. Note sulla Realizzazione del DW con architettura ad 1 livello 1 Schema sorgente : ORARI 2
Schema sorgente : CREDITI 3 Documentazione dello schema! Se un insegnamento ha un unico SSD (Settore Scientifico Disciplinare) allora " Il numero di crediti relativi viene specificato in Insegnamenti " C è una sola tupla nella tabella Insegnamenti_Corsi_SSD! Altrimenti " I crediti vengono specificati in Insegnamenti_Corsi_SSD, con la possibilità di suddividerli in base alla tipologia (CFU_base, CFU_Affini, CFU_Carat,CFU_Sede e CFU_Altre); chiameremo tali crediti, crediti dettagliati " In questo caso il numero di Crediti in Insegnamenti è nullo (in quanto equivale alla somma dei vari crediti specifici)! L associazione tra insegnamenti e attività è molti a molti, con partecipazione opzionale di Insegnamenti: ovvero ci sono alcuni insegnamenti con nessuna attività associata 4
Analisi dei dati! Nel seguito faremo un analisi dei dati, tramite alcuni esempi, allo scopo di individuare eventuali problemi di inconsistenza dei dati del DataBase reale rispetto alle specifiche riportate nella documentazione! Inoltre, in base a tale analisi, verrà definito il DB riconciliato! L analisi dei dati è un attività da condurre in collaborazione con l amministratore del DB, sia perchè può richiedere una conoscenza approfondita dello schema dei dati sia perche in alcuni casi può richiedere l esecuzione di query SQL non banali 5 Analisi dei dati / Crediti! Esempio: Allo scopo di verificare se la regola sui crediti è rispettata effettuiamo un interrogazione per vedere se ci sono insegnamenti con il campo CREDITI non nullo (CREDITI IS NOT NULL) ma con più di un SSD associato SELECT IdInsegnamento,COUNT(*) FROM TBL_INSEGNAMENTI_CORSI_SSD WHERE IdInsegnamento IN( SELECT TBL_INSEGNAMENTI.ID FROM TBL_INSEGNAMENTI WHERE CREDITI IS NOT NULL) GROUP BY IdInsegnamento HAVING COUNT(*) >1 " Risultato (ci sono 9 tuple su 4272). Ad esempio, l insegnamento 519 non rispetta la regola: ha CREDITI non nullo e due SSD associati 6
Analisi dei dati / Crediti! Quanti sono gli insegnamenti con Crediti nullo? 347 SELECT COUNT(*) FROM TBL_INSEGNAMENTI WHERE CREDITI IS NULL! Quanti sono gli insegnamenti con almeno un Credito specifico riportato in TBL_INSEGNAMENTI_CORSI_SSD? 1067 (Questa interrogazione è fatta tramite una vista in modo da poterla riutilizzare nel seguito, in altre interrogazioni) CREATE VIEW VIEW_CREDITI_SPECIFICI_NON_NULL AS SELECT * FROM TBL_INSEGNAMENTI_CORSI_SSD WHERE (CFU_Sede IS NOT NULL) OR (CFU_Altre IS NOT NULL) OR (CFU_Base IS NOT NULL) OR (CFU_Caratt IS NOT NULL) OR (CFU_Affini IS NOT NULL) SELECT COUNT(*) FROM VIEW_CREDITI_SPECIFICI_NON_NULL 7 Analisi dei dati / Crediti! Quali sono gli insegnamenti con un valore di Crediti non NULLO e diverso dalla somma dei crediti dettagliati riportati in TBL_INSEGNAMENTI_CORSI_SSD? NESSUNO! SELECT * FROM TBL_INSEGNAMENTI WHERE (Crediti IS NOT NULL) AND (Crediti <> (SELECT SUM(isnull(CFU_Sede, 0) + isnull(cfu_altre, 0) + isnull(cfu_base, 0) + isnull(cfu_caratt, 0) + isnull(cfu_affini, 0)) FROM VIEW_CREDITI_SPECIFICI_NON_NULL WHERE IdInsegnamento = TBL_INSEGNAMENTI.ID GROUP BY IdInsegnamento)) 8
Analisi dei dati / Crediti! Se un insegnamento ha crediti null in TBL_INSEGNAMENTI, posso ricavarlo facendo la somma dei crediti dettagliati? NO, perchè! Quali sono gli insegnamenti con un valore di CREDITI null in TBL_INSEGNAMENTI e con la somma diversa da zero dei crediti specifici riportati in TBL_INSEGNAMENTI_CORSI_SSD? NESSUNO! SELECT * FROM TBL_INSEGNAMENTI WHERE (Crediti IS NOT NULL) AND (0 <> (SELECT SUM(isnull(CFU_Sede, 0) + isnull(cfu_altre, 0) + isnull(cfu_base, 0) + isnull(cfu_caratt, 0) + isnull(cfu_affini, 0)) FROM VIEW_CREDITI_SPECIFICI_NON_NULL WHERE IdInsegnamento = TBL_INSEGNAMENTI.ID GROUP BY IdInsegnamento)) 9 Analisi dei dati / Crediti : conclusioni! La tabella TBL_INSEGNAMENTI_CORSI_SSD non aggiunge informazione sul numero dei crediti complessivi di un insegnamento, quindi è inutile fare la somma dei crediti in essa riportata per assegnarla come Crediti in TBL_INSEGNAMENTI! Decisione: Non si considerano i crediti dettagliati.! Decisione: nel livello riconciliato dei dati si considera un associazione unoa-molti tra Insegnamenti e SSD " In TBL_INSEGNAMENTI viene aggiunto un campo IdSSD " Nel caso di insegnamenti con più SSD si considera un solo SSD a caso, ottenibile, ad esempio, come SSD con massimo valore di ID, cioè tra tutti gli SSD associati all insegnamento prendo quello il cui ID ha valore massimo. Usiamo questa tecnica perchè facilmente implementabile in SQL tramite la funzione MAX; naturalmente si potrebbe definire una funzione più complessa. 10
Analisi dei dati / Attività! Con un procedimento analogo al precedente si analizza l associazione tra gli insegnamenti e le attività, verificando che non ci sono insegnamenti con più di una attività associata SELECT IdInsegnamento FROM TBL_INSEGNAMENTI_ATTIVITA group by IdInsegnamento having count(*) > 1 " Risultato vuoto: non ci sono insegnamenti con più di una attività associata! Decisione: nel livello riconciliato dei dati si considera un associazione uno-a-molti tra Insegnamenti e Attività: In TBL_INSEGNAMENTI verrà considerato il campo IdAttività in cui viene riportato l ID dell unica attività associata " Conviene calcolare tale ID come valore max tra tutti gli ID delle attività associate all insegnamento: in questo modo se verranno inseriti degli insegnamenti con più attività, nello schema riconciliato si riesce comunque ad individuare una sola attività 11 Livello riconciliato: Crediti e Attività 12
Analisi dei dati / Orari! Un aspetto evidente dello schema degli orari è l assenza di una chiave in TBL_INS_ORARIO. Questo significa che non sono dichiarati i classici vincoli " non sovrapposizione: non ci sono due insegnamenti nello stesso ora nella stessa aula. Si può verificare che non è vero, in quanto la seguente query restituisce un risultato non vuoto: SELECT Id_Anno, Id_Periodo, Id_Giorno, Id_Ora, Id_Aula FROM TBL_INS_ORARIO GROUP BY Id_Anno, Id_Periodo, Id_Giorno, Id_Ora, Id_Aula HAVING (COUNT(DISTINCT Id_Ins) > 1) " non sdoppiamento: in un certo orario, un insegnamento è in una sola aula. Si può verificare che non è vero, in quanto la seguente query restituisce un risultato non vuoto: SELECT Id_Ins, Id_Anno, Id_Periodo, Id_Giorno, Id_Ora FROM TBL_INS_ORARIO GROUP BY Id_CDS, Id_Ins, Id_Anno, Id_Periodo, Id_Giorno, Id_Ora HAVING (COUNT(DISTINCT Id_Aula) > 1) 13 Analisi dei dati / Orari! Un altro aspetto è la denormalizzazione della tabella INS_ORARIO: ci sono alcuni campi che, intuitivamente, dipendono da altri campi. " Dipendenza Id_periodo! Id_Anno Per verificare questa dipendenza funzionale ricavo i valori di Id_periodo che hanno differenti Id_anno associati: SELECT Id_periodo FROM TBL_INS_ORARIO group by Id_Periodo having count(distinct Id_Anno) > 1 " Il risultato è vuoto, quindi, sull istanza corrente, la dipendenza è verificata. " Verifichiamo che Id_Anno in INS_ORARIO sia lo stesso IdAA indicato in TBL_PERIODI: SELECT count(*) FROM TBL_INS_ORARIO JOIN TBL_PERIODI ON TBL_INS_ORARIO.Id_Periodo = TBL_PERIODI.Id where TBL_INS_ORARIO.Id_Anno <> TBL_PERIODI.IdAA! Decisione: Id_Anno si può eliminare dalla tabella INS_ORARIO. 14
Analisi dei dati / Orari! Come altro esempio di potenziale dip. funz., consideriamo se in INS_ORARIO l insegnamento (Id_Ins) determina il Corso di Studio (Id_cds) " Dipendenza Id_Ins! Id_Cds Per verificare questa dip. Funz. ricavo i valori di Id_Ins che hanno differenti Id_Cds associati: SELECT Id_Ins FROM TBL_INS_ORARIO group by Id_Ins having count(distinct Id_CDS) > 1 " Il risultato della query non è vuoto: Cosa significa questo? Perche in INS_ORARIO non ho solo il CDS di Id_Ins (quello specificato in TBL_INSEGNAMENTI come Id_CorsoStudioRegolamento)? " Analizzando alcune tuple, ma soprattutto chiedendo all amministratore del DB, si scopre che viene seguita la seguente regola: sia X un insegnamento con del Corso di studi CDSX che mutua da un insegnamento Y del Corso di studi CDSY; allora tutte le ore di X in INS_ORARIO vengono messe con Id_Ins=Y e Id_Cds=CDSX! Decisione: Id_Cds resta nella tabella INS_ORARIO. 15 Analisi dei dati / Orari - Mutuazioni! Esempio: consideriamo due insegnamenti (SI, SI&BD) con i relativi Corsi di Studio indicati nella tabella INSEGNAMENTI TBL_INSEGNAMENTI ID IDCORSODISTUDIOREGOLAMENTO SI E-BUS SI&BD GEST_IND! Orario (A.A. 2003/2004, periodo=3) " Lunedi, ore 9-11, SI e SI&BD, aula F " Martedì!, ore 9-10, SI, aula G " Mercoled!ì, ore 10-10, SI&BD, aula H! In base alla precedente regola, in INS_ORARIO si ha: TBL_INS_ORARIO ID_CDS ID_ANNO ID_PERIODO ID_INS ID_GIORNO ID_ORA ID_AULA E-BUS 2003/2004 3 SI&BD 1 2 F E-BUS 2003/2004 3 SI&BD 1 3 F GEST_IND 2003/2004 3 SI&BD 1 2 F GEST_IND 2003/2004 3 SI&BD 1 3 F E-BUS 2003/2004 3 SI&BD 2 2 G GEST_IND 2003/2004 3 SI&BD 3 3 H! Se non si considerano le mutuazioni, tutte le ore vengono assegnate a SI&BD ma questo può essere non significativo per alcune tipologie di analisi (ad esempio, se l insegnamento ha un docente, e chiedo qual è l impegno - ovvero il numero di ore - del docente dovrei considerare le mutuazioni). 16
Livello riconciliato : schema complessivo 17 Dove si realizza lo schema riconciliato? 1. Architettura a 3 livelli si realizza un nuovo DB (DBRiconciliato) con lo schema riconciliato: Dati operazionali Dati esterni Livello delle sorgenti Strumenti ETL DBRiconciliato Caricamento Dati riconciliati Meta-dati Livello di alimentazione Data Warehouse Livello del warehouse! Il nuovo DBRiconciliato deve essere alimentato con i dati originali: si può usare il DTS di SQL Server (vedi ultima parte) 18
Alimentazione del DBRiconciliato! Esempio: Tabella TBL_INSEGNAMENTI 1. Si crea la tabella TBL_INSEGNAMENTI dello schema riconciliato 2. Tramite DTS si copiano i campi di TBL_INSEGNAMENTI i cui valori restano inalterati nel DBRiconciliato 3. Si determinano gli altri campi della tabella ; in questo caso occorre calcolare IdSSD come valore massimo dei valori presenti in TBL_INSEGNAMENTI_CORSI_SSD, allora 1. Si effettua una copia temporanea in DBRiconciliato di TBL_INSEGNAMENTI_CORSI_SSD) 2. Si esegue la seguente istruzione UPDATE TBL_INSEGNAMENTI SET IdSSD = (SELECT max(idssd) FROM TBL_INSEGNAMENTI_CORSI_SSD_TEMP WHERE TBL_INSEGNAMENTI.Id = idinsegnamento)! Alternative (più difficili da implementare) " IdSSS viene calcolato tramite una query nel DTS " IdSSS viene calcolato tramite una vista nel DB originale 19 Dove si realizza lo schema riconciliato? 2. Architettura a 2 livelli Non si realizza un nuovo DB riconciliato Livello delle sorgenti Dati operazionali Dati esterni Strumenti ETL Livello di alimentazione Data Warehouse Livello del warehouse! La riconciliazione viene effettuata direttamente nel DB originale, tramite l aggiunta di opportune tabelle e/o viste, cioè lo schema riconciliato di pag. 17 viene realizzato nel DB originale.! Uso di tabelle: Lo schema riconciliato viene realizzato nel DB originale introducendo solo le tabelle variate (es. TBL_INSEGNAMENTI) ed eventualmente nuove tabelle; le altre tabelle (es. TBL_ATTIVITA) la cui struttura non è stata modificata restano invariate 20
Architettura a 2 livelli : uso di tabelle! Le tabelle variate (es. TBL_INSEGNAMENTI) ed eventualmente le nuove tabelle si costruiscono tramite tabelle (il cui nome è seguito da _RIC per ricordare che sono dello schema riconciliato)! Esempio: Tabella TBL_INSEGNAMENTI_RIC 1. Si crea la tabella TBL_INSEGNAMENTI_RIC dello schema riconciliato 2. Si copiano i campi di TBL_INSEGNAMENTI i cui valori restano inalterati nello schema riconciliato INSERT INTO TBL_INSEGNAMENTI_RIC(Id, IdCorsoStudioRegolamento, Denominazione, Crediti, IdAmbito, IdAttivita, AnnoCorso, Asterisco) SELECT Id, IdCorsoStudioRegolamento, Denominazione, Crediti, IdAmbito, IdAttivita, AnnoCorso, Asterisco FROM TBL_INSEGNAMENTI 3. Si determinano gli altri campi della tabella; nell esempio IdSSD: UPDATE TBL_INSEGNAMENTI_RIC SET IdSSD = (SELECT max(idssd) FROM TBL_INSEGNAMENTI_CORSI_SSD WHERE TBL_INSEGNAMENTI_RIC.Id = idinsegnamento) " Le istruzioni 2 e 3 possono essere eseguite in un pacchetto DTS, (precedute da uno svuotamento dell tabella TBL_INSEGNAMENTI_RIC)! Si consiglia di utilizzare questa modalità nella tesina 21 Architettura a 2 livelli: uso di viste! Lo schema riconciliato (vedi p. 17) si realizza nel DB originale definendo le tabelle variate e le eventuali nuove tabelle come viste! La definizione delle viste può risultare difficile, in quanto occorre considerare, in genere, sia campi invariati sia campi calcolati!! Esempio: TBL_INSEGNAMENTI_RIC definita come vista 1. Si definisce la vista V1 che riporta i campi di TBL_INSEGNAMENTI i cui valori restano inalterati nello schema riconciliato CREATE VIEW V1 AS SELECT Id, IdCorsoStudioRegolamento, Denominazione, Crediti, IdAmbito, IdAttivita, AnnoCorso, Asterisco FROM TBL_INSEGNAMENTI 2. Per ogni campo calcolato (es. IdSSD) si definisce una vista avente come attributi la chiave di TBL_INSEGNAMENTI e il campo calcolato; CREATE VIEW V2(ID,IdSSD) as SELECT idinsegnamento,max(idssd) FROM TBL_INSEGNAMENTI_CORSI_SSD GROUP BY idinsegnamento 3. La vista TBL_INSEGNAMENTI_RIC è il join di V1 e V2 : CREATE VIEW TBL_INSEGNAMENTI_RIC( tutti gli attributi ) AS SELECT V1.*, IdSSD FROM V1, V2 WHERE V1.ID=V2.ID 22
Schema di Fatto - Orari! Punti caratteristici: " La tabella INS_ORARIO non ha una chiave e l insieme di attributi non è chiave: Nel corrispondente schema E/R considero un codice fittizio (nota: in base alle specifiche so già che sarà uno schema a grana temporale, nel quale questo codice scomparirà) " Convergenza? L AnnoAccademico indicato in Periodi è lo stesso di quello riportato in CorsoDiStudiRegolamento? Si, ad eccezione di 25 tuple su circa 10.000! Possiamo indicare la convergenza (eventualmente si possono pulire le tuple sporche). La convergenza non influenza il nostro progetto logico " Granularità a livello di ora: Non si vuole considerare la singola ora, ma solo differenziare tra 'mattina' e pomeriggio : si definisce una dimensione MATPOM derivata da ID_ORA. Per semplicità (come nel caso dell attributo CHECK_IN nell esempio dei biglietti) si aggiunge alla tabella INS_ORARIO un attributo MATPOM con valori mat e pom calcolato direttamente sul DB transazionale: update TBL_INS_ORARIO set MATPOM= mat where ID_ora >=0 and ID_ora<=5 update TBL_INS_ORARIO set MATPOM= pom where ID_ora >=6 " Senza considerare le mutuazioni si definisce solo la misura NUM_ORE = count(*) 23 Schema di Fatto - Orari - Mutuazioni! Per tenere conto delle mutuazioni : " non ho informazioni sulle mutuazioni nello schema " NUM_ORE_EFFETTIVE (cioè ore non mutuate da altri CDS) : Si deve innanzitutto definire cosa significa non mutuata considerando la regola precedente, e quindi si può procedere al calcolo. Nel lucido che segue verrà presentato tale calcolo; per semplicità nel calcolo (della espressioni SQL) si aggiunge alla tabellla INS_ORARIO un campo MUTUATA che riporta appunto l esito di tale calcolo! Esempio: Orario (A.A. 2003/2004, periodo=3) " Lunedi, ore 9-11, SI e SI&BD, aula F " Martedì!, ore 9-10, SI, aula G " Mercoled!ì, ore 10-10, SI&BD, aula H TBL_INSEGNAMENTI ID IDCORSODISTUDIOREGOLAMENTO SI E-BUS SI&BD GEST_IND! In base alla regola, in INS_ORARIO si ha: TBL_INS_ORARIO ID_CDS ID_ANNO ID_PERIODO ID_INS ID_GIORNO ID_ORA ID_AULA MUTUATA E-BUS 2003/2004 3 SI&BD 1 2 F SI E-BUS 2003/2004 3 SI&BD 1 3 F SI GEST_IND 2003/2004 3 SI&BD 1 2 F NO GEST_IND 2003/2004 3 SI&BD 1 3 F NO E-BUS 2003/2004 3 SI&BD 2 2 G NO GEST_IND 2003/2004 3 SI&BD 3 3 H NO 24
Schema di Fatto - Orari - Mutuazioni! Calcolo dell attributo MUTUATA 1. Per default, un ora è non mutuata : update TBL_INS_ORARIO set MUTUATA='NO' 2. Un ora è mutuata se (a) ID_CDS è diverso da IDCORSODISTUDIOREGOLAMENTO nella tabella INSEGNAMENTI e (b) c è una corrispondente ora (stessa ora, stesso giorno, stessa aula,stesso anno e periodo) con differente ID_CDS update TBL_INS_ORARIO set MUTUATA='SI' where ID_CdS <> (select idcorsostudioregolamento from TBL_INSEGNAMENTI where TBL_INS_ORARIO.ID_ins = TBL_INSEGNAMENTI.Id) and exists (select * from TBL_INS_ORARIO as O1 where TBL_INS_ORARIO.ID_Anno=O1.Id_anno and TBL_INS_ORARIO.Id_periodo=O1.Id_periodo and TBL_INS_ORARIO.Id_giorno=O1.Id_giorno and O.Id_ora=O1.Id_ora and TBL_INS_ORARIO.Id_aula=O1.Id_aula and O.ID_CDS<>O1.Id_CDS) 25 Progetto Logico 26
Alimentazione del DM! L alimentazione delle Dimension Table è semplice: la loro struttura corrisponde a quelle del DB transazionale; utilizzare importa dati rispettando l ordine imposto dalle FK (vedi esempi DTS)! Per l alimentazione della Fact Table si definisce una vista nel DB originale, contenente tutte le misure! In questo caso NUM_ORE si calcola su tutte le tuple di INS_ORARIO mentre NUM_ORE_EFF solo su quelle con Mutuata = No : conviene definire due viste e poi fare il join! Vista per il Calcolo di NUM_ CREATE VIEW ConteggioOre(Id_CDS, Id_Periodo, Id_Ins, Id_Giorno,Id_Aula, MatPom,NUM_ORE) AS SELECT Id_CDS, Id_Periodo, Id_Ins, Id_Giorno, Id_Aula, MatPom, count(*) FROM TBL_INS_ORARIO group by Id_CDS, Id_Periodo, Id_Ins, Id_Giorno, Id_Aula, MatPom! Vista per il Calcolo di NUM_ CREATE VIEW ConteggioOreEffettive (Id_CDS, Id_Periodo, Id_Ins, Id_Giorno,Id_Aula, MatPom,NUM_ORE_EFF) AS SELECT Id_CDS, Id_Periodo, Id_Ins, Id_Giorno, Id_Aula, MatPom, count(*) FROM TBL_INS_ORARIO where Mutuata = No' group by Id_CDS, Id_Periodo, Id_Ins, Id_Giorno, Id_Aula, MatPom! Nota: si potrebbero usare queste due viste per alimentare la Fact Table, però l alimentazione in DTS risulta più complessa: si preferisce creare una sola vista. 27 Vista per il calcolo delle misure! Vista con entrambi i valori calcolati : è ottenuta (usare l interfaccia grafica) come join delle due precedenti viste " Siccome ConteggioOre ha un sovrainsieme delle tupe di ConteggioOreEffettive, usare ConteggioOre Left Join ConteggioOreEffettive " Usare isnull(num_ore_eff,0) : in questo modo per una tupla che è in ConteggioOre ma non in ConteggioOreEffettive (cioè è mutuata) ho 0 come valore di NUM_ORE_EFF CREATE VIEW dbo.conteggioentrambe AS SELECT dbo.conteggioore.id_cds, dbo.conteggioore.id_periodo, dbo.conteggioore.id_ins, dbo.conteggioore.id_giorno, dbo.conteggioore.id_aula, dbo.conteggioore.matpom, dbo.conteggioore.num_ore, isnull(dbo.conteggiooreeffettive.num_ore_eff,0) as NUM_ORE_EFF FROM dbo.conteggioore LEFT OUTER JOIN dbo.conteggiooreeffettive ON dbo.conteggioore.matpom = dbo.conteggiooreeffettive.matpom AND dbo.conteggioore.id_aula = dbo.conteggiooreeffettive.id_aula AND dbo.conteggioore.id_giorno = dbo.conteggiooreeffettive.id_giorno AND dbo.conteggioore.id_ins = dbo.conteggiooreeffettive.id_ins AND dbo.conteggioore.id_periodo = dbo.conteggiooreeffettive.id_periodo AND dbo.conteggioore.id_cds = dbo.conteggiooreeffettive.id_cds 28
Realizzazione Cubi in Analysis Services! Consideriamo la Dimensione Periodo con la relativa gerarchia " TipoPeriodo è la denominazione del periodo.! In Analysis Services possiamo definire due dimensioni: " Nota: nella dimensione TipoPeriodo si decide di non considerare il livello IdPeriodo; è una modifica rispetto al progetto concettuale iniziale 29 Alcuni esempi di query MDX! Nel seguito vengono riportati alcuni esempi di query MDX sul cubo ORARI! Esempio: Ore mutuate (definite come differenza tra le ore e quelle effettive): COLUMNS: i primi 7 CDS che hanno un maggior numero di ore mutuate ROWS: I periodi del 2004/2005gli Anni Accademici Si mostrano le ore mutuate WITH MEMBER [MEASURES].[NUM_ORE_MUTUATE] AS '[Measures].[Num Ore]- [Measures].[Num Ore Eff]' SELECT TOPCOUNT([CDS].[Denominazione].MEMBERS, 7, [NUM_ORE_MUTUATE]) ON COLUMNS, [Periodo].[2004/2005].CHILDREN ON ROWS FROM ORARI WHERE [NUM_ORE_MUTUATE] Problema: in questo modo il TopCount ordina rispetto a [NUM_ORE_MUTUATE] complessive, non quelle del 2004/2005. Per ordinare rispetto a quelle del 2004/2005 : ([Periodo].[2004/2005],[NUM_ORE_MUTUATE]) WITH MEMBER [MEASURES].[NUM_ORE_MUTUATE] AS '[Measures].[Num Ore]- [Measures].[Num Ore Eff]' SELECT TOPCOUNT([CDS].[Denominazione].MEMBERS, 7, ([Periodo].[2004/2005],[NUM_ORE_MUTUATE]))ON COLUMNS, [Periodo].[2004/2005].CHILDREN ON ROWS FROM ORARI WHERE [NUM_ORE_MUTUATE] 30
Alcuni esempi di query MDX! Esempio: Ore per AnnoAccademico/Periodo e AnnoDiCorso/CorsodiStudi " COLUMNS: (X,Y), dove X è un Anno Accademico e Y un TipoPeriodo NONEMPTYCROSSJOIN( [Periodo].[AnnoAccademico].MEMBERS, [TipoPeriodo].[TipoPeriodo].MEMBERS ) ON COLUMNS " ROWS : (X,Y), dove X è un Anno di Corso e Y è un Corso di Studi, limitato a Informatica ed Elettronica: NONEMPTYCROSSJOIN( [Anno Corso].[Anno Corso].MEMBERS, {[CDS].[Ingegneria Elettronica], [CDS].[Ingegneria Informatica] }) ON ROWS " Se invece di Informatica ed Elettronica voglio i primi tre Cds per numero di ore: NONEMPTYCROSSJOIN( [Anno Corso].[Anno Corso].MEMBERS, TOPCOUNT([CDS].[Denominazione].MEMBERS,3,[Measures].[Num Ore])}) ON ROWS 31 Architetture a 1 livello! Si discute brevemente questo tipo di soluzione nell esempio.! Alla fine della progettazione logica, si ha lo schema logico (pag. 26) su carta.! Il livello del warehouse è costituito da un insieme di viste nel DB operazionale: si può definire una vista corrispondente alla fact table FT_ORARI partendo dalla vista ConteggioEntrambe (pag. 28); per le dimension table si usano direttamente le table operazionale. Dati operazionali Middleware Strumenti OLAP Livello delle sorgenti Livello del warehouse Livello di analisi! Il livello di analisi (i cubi) verranno definiti usando come sorgente dati il DB operazionale; un cubo può essere definito a partire da una vista.! Prescindendo dai noti problemi di efficienza, elenchiamo alcuni pro e contro: " Pro: Alcuni analisi (cubi) si realizzano in modo immediato; ad esempio, possiamo analizzare il numero di ore rispetto al giorno e al cds anche senza realizzare alcuna vista ma riferendoci direttamente alla tabella INS_ORARIO " Contro: Per analisi più complete/complesse, che coinvolgono particolari dimensioni (es. MatPom) e/o misure (es. Num_Ore_Eff) occorre definire delle viste non banali oppure effettuare complessi calcoli (misure, dimensioni) usando lo 32 specifico strumento OLAP (Analysis Services nel nostro caso).