Schema Del DB Operazionale TELEFONATE Costruire lo Schema di Fatto per analizzare le chiamate considerando come dimensioni TelefonoDA e TelefonoA, Data e Fascia, intesa come FasciaOraria della chiamata e calcolata in base a Ora sulla base della seguente codifica: Fascia = CASE WHEN Ora BETWEEN 0 AND 6 THEN 'Notte' WHEN Ora BETWEEN 7 AND 13 THEN 'Mattina' WHEN Ora BETWEEN 14 AND 20 THEN 'Pomeriggio' WHEN Ora BETWEEN 21 AND 23 THEN 'Sera' Considerare come misure il Costo, la Durata, il Numero (di chiamate effettuate) e la MediaOraria (ovvero il numero medio di telefonate fatte in un ora). Progettazione concettuale Fatto CHIAMATA Key = { Data, Ora, Minuto, DaPrefisso, APrefisso} Albero degli attributi: Riportiamo l albero degli attributi così come ottenuto automaticamente dallo strumento case WAND.
Osservazioni: 1) Il nome della radice viene sintetizzato con il nome del fatto (CHIAMATA) invece di esplicitare tutta la relativa key: Data + Ora + Minuto + DaPrefisso + APrefisso 2) L aspetto più importante sono i due nodi a. DaPrefisso + DaNumero b. APrefisso + ANumero Che derivano dalle due foreign key presenti in chiamata e riferite a telefono: essendo la chiave di telefono composta da Prefisso e Numero, il relativo nodo è identificato da questi due attributi. Dopo aver eliminato i nodi che non vogliamo prendere in considerazione durante l analisi (il numero di telefono e il minuto della chiamata) si ottiene il seguente schema di fatto:
Osservazioni: 1) Un attributo dimensionale deve essere semplice, ovvero non può essere composto da due o più campi, quindi al nodo DaPrefisso + DaNumero facciamo corrispondere un attributo dimensionale DaTelefono : I valori di tale attributo dimensionale si otterranno come combinazione (ad esempio, come concatenazione) dei valori dei due singoli attributi DaPrefisso e DaNumero; stessa cosa per il nodo APrefisso + ANumero che corrisponderà all attributo dimensionale ATelefono 2) Le due dimensioni DaTelefono e ATelefono possono essere rappresentate tramite la gerarchia condivisa Telefono Dimensioni : { Data, FasciaOraria, DaTelefono, ATelefono } Le dimensioni non contengono la chiave del Fatto CHIAMATA quindi lo schema è temporale: le misure indicate devono essere ottenute con una funzione di aggregazione Glossario delle misure: Costo Durata Numero = SUM(Chiamata.Costo) = SUM(Chiamata.Durata) = COUNT(*) MediaOraria = AVG ( <NumeroChiamatePerOgniOra>), dove <NumeroChiamatePerOgniOra> riporta per ogni ora il relativo numero di chiamate, ovvero si ottiene raggruppando su ora ed effettuando un conteggio. Per esempio, con
devo ottenere (rispetto a Data e FAsciaOraria) Questo esempio mette in evidenza che in uno schema temporale l espressione che definisce una misura può essere anche complesso. Le misure devono essere calcolate considerando il raggruppamento sulle dimensioni. Ricaviamo le dimensioni calcolate, ovvero ottenute tramite elaborazione da attributi dello schema relazionale 1) L attributo dimensionale Fascia verrà calcolata sulla base della codifica introdotta 2) L attributo dimensionale Telefono varrrà calcolato come concatenazione di Prefisso + Numero Per ognuna delle dimensioni calcolate verrà definite una vista che riporta la dimensione calcolata e gli attributi usati nella sua definizione: create view Fascia(Ora, Fascia) as select DISTINCT Ora, Fascia = CASE WHEN Ora BETWEEN 0 AND 6 THEN 'Notte' WHEN Ora BETWEEN 7 AND 13 THEN 'Mattina' WHEN Ora BETWEEN 14 AND 20 THEN 'Pomeriggio' WHEN Ora BETWEEN 21 AND 23 THEN 'Sera' END From CHIAMATA create view NumeroIntero(Prefisso,Numero,NumeroIntero)
as select Prefisso,Numero CAST ( Prefisso AS VARCHAR ) + CAST( Numero AS VARCHAR ) AS NumeroIntero From TELEFONO Note: 1) Queste viste sono create nello stesso DB operazionale; siccome c e già una tabella Telefono non posso avere una vista chiamata Telefono si usa NumeroIntero 2) L operazione di casting CAST ( Prefisso AS VARCHAR ) serve per convertire il Prefisso che è un intero in una stringa in modo da poterlo combinare tramite l operatore + di concatenazione di stringhe Come verranno usate queste viste? Se serve la fascia oraria relativa ad un ora, farò il join tra la trabella T che contiene l ora e la vista Fascia, join su T.ora=Fascia.Ora! Ad esempio, per calcolare Costo = SUM(Chiamata.Costo) rispetto alla fascia oraria: Mentre per calcolare Costo = SUM(Chiamata.Costo) rispetto al telefono chiamante devo inserire anche la vista NumeroIntero:
A questo punto possiamo esplicitare il calcolo delle misure considerando il raggruppamento sulle dimensioni. Dimensioni : { Data, FasciaOraria, DaTelefono, ATelefono } Data DaTelefono ATelefono FasciaOraria dalla tabella CHIAMATA dalla tabella CHIAMATA + join con la view NumeroIntero dalla tabella CHIAMATA + join con la view NumeroIntero dalla tabella CHIAMATA + join con la view Fascia Il join tra queste viste deve essere fatto sulla base delle FK definite nello schema operazionale, ovvero sulla base degli attributi Prefisso,Numero Importante: DaTelefono e ATelefono sono due valori indipendenti e quindi per selezionare devo inserire due volte la view NumeroIntero; in altre parole ho due FK, devo inserire due volte la view NumeroIntero Ultima cosa è definire il calcolo della misura MediaOraria = AVG ( <NumeroChiamatePerOgniOra>), dove <NumeroChiamatePerOgniOra> riporta per ogni ora il relativo numero di chiamate, ovvero si ottiene raggruppando su ora ed effettuando un conteggio.
In altre parole <NumeroChiamatePerOgniOra> si ottiene dalla seguente interrogazione (vista): e quindi la MediaOraria si otterrà come AVG (NChiamate Ora.Numero). Ad esempio per valutare questo valore rispetto alla Fascia Oraria
La media è calcolata considerando Numero come intero: per avere anche i valori decimali devo fare un casting di tale attributo ad un tipo real (quale DECIMAL) : Facciamo lo stesso calcolo considerando Data e Ora
e quindi facciamo il join con FASCIA per calcolare la MediaOraria (per valutare il risultato si seleziona una data specifica )
In questo esempio è stato illustrato l uso delle viste per un calcolo complesso: dovendo calcolare la media di un conteggio e non potendolo fare direttamente in SQL perché le funzioni aggregate non possono essere innestate, si usa una vista intermedia per calcolare il conteggio e quindi si applica la media sui valori di tale vista. In realtà in questo caso specifico si può anche calcolare la MediaOraria come segue, senza ricorrere alla vista intermedia:
e per evitare il solito problema della divisione tra interi:
Progettazione Logica (Star Schema)
GENERAZIONE DI TUPLE Uso del tool:
La data contiene anche il time : In effetti potevamo non riempire Ora e Minuto e ottenerlo dalla Data, tramite la funzione DATEPART update Chiamata set Ora = DATEPART ( hour, data ) update Chiamata set Minuto = DATEPART ( minute, data ) Verifichiamo:
La data contiene anche il time : come ottenere in Data solo la data (ovvero con un time =00: )? Questo è fondamentale altrimenti i due valori la stessa data (2004-05-27) con time diverso e considerato differente come si può verificare dalla query: Dal manuale si individua la funzione CONVERT. update chiamata set data=convert(varchar,data,105) verifichiamo
anche con : update Chiamata set DaPrefisso = (select Prefisso from NumeroIntero where NumeroIntero.NumeroIntero=Chiamata.DaTel) update Chiamata set DaNumero = (select Numero from NumeroIntero where NumeroIntero.NumeroIntero=Chiamata.DaTel)
update Chiamata set APrefisso = (select Prefisso from NumeroIntero where NumeroIntero.NumeroIntero=Chiamata.ATel) update Chiamata set ANumero = (select Numero from NumeroIntero where NumeroIntero.NumeroIntero=Chiamata.ATel) Verifichiamo Orale le due colonne temporanee si possono eliminare