Anteprima
Vedrai una selezione di 10 pagine su 56
Appunti Basi di Dati - completi Pag. 1 Appunti Basi di Dati - completi Pag. 2
Anteprima di 10 pagg. su 56.
Scarica il documento per vederlo tutto.
Appunti Basi di Dati - completi Pag. 6
Anteprima di 10 pagg. su 56.
Scarica il documento per vederlo tutto.
Appunti Basi di Dati - completi Pag. 11
Anteprima di 10 pagg. su 56.
Scarica il documento per vederlo tutto.
Appunti Basi di Dati - completi Pag. 16
Anteprima di 10 pagg. su 56.
Scarica il documento per vederlo tutto.
Appunti Basi di Dati - completi Pag. 21
Anteprima di 10 pagg. su 56.
Scarica il documento per vederlo tutto.
Appunti Basi di Dati - completi Pag. 26
Anteprima di 10 pagg. su 56.
Scarica il documento per vederlo tutto.
Appunti Basi di Dati - completi Pag. 31
Anteprima di 10 pagg. su 56.
Scarica il documento per vederlo tutto.
Appunti Basi di Dati - completi Pag. 36
Anteprima di 10 pagg. su 56.
Scarica il documento per vederlo tutto.
Appunti Basi di Dati - completi Pag. 41
1 su 56
D/illustrazione/soddisfatti o rimborsati
Disdici quando
vuoi
Acquista con carta
o PayPal
Scarica i documenti
tutte le volte che vuoi
Estratto del documento

MATERIALIZZAZIONE

Materializzo il fatturato (per store, giorno) in una tabella CREATE TABLE

CREATE TABLE f Crea una tabella con la

SELECT store, data, SUM(importo) AS tot_importo struttura e i contenuti uguali al

risultato della query seguente

FROM tab_vendite

GROUP BY store, data;

Calcolo le ore lavorate (per supermercato, giorno) e materializzo La coppia di attributi

CREATE TABLE h <store, data> funge da

SELECT store, data, SUM(ore_lavorate) AS tot_ore chiave nella tabella

output

FROM tab_ore_lavorate

GROUP BY store, data;

A questo punto posso scrivere la query: Nelle tabelle materializzate

SELECT f.data, f.store, “f” ed “h”, i record hanno la

stessa granularità (entrambe

f.tot_importo / h.tot_ore FROM f, h hanno store e data come chiavi)

WHERE f.store=h.store AND f.data=h.data;

VISTE

Vista (o view): è una tabella virtuale associata al risultato di una query

La vista non esiste realmente, ogni volta che viene interrogata una vista, il DBMS esegue la query associata

Sintassi per la creazione di una vista: CREATE VIEW nome_view AS query …;

Es. CREATE VIEW Importo AS

SELECT store, data, SUM(importo) AS tot_importo

FROM tab_vendite

GROUP BY store, data;

Le viste, si usano come se fossero normali tabelle

Materializzazione VS viste

La materializzazione crea problemi

- spazio occupato

- disallineamenti nel caso di aggiornamento dei dati

Le viste risolvono i problemi di spazio occupato e aggiornamento, ma …

- le viste sono onerose da gestire per il DBMS

- ha senso creare una vista solamente se i dati saranno utilizzati più di una volta

- se una vista viene utilizzata spesso, conviene passare alla materializzazione

QUERY ANNIDATE

Ricordiamo che una query opera sulle tabelle indicate dopo la clausola FROM.

Per poter calcolare lo stesso risultato senza materializzare …

Dovremmo poter scrivere una query che oltre ad operare su tabelle esistenti riesca a lavorare a partire dai

risultati di altre query.

Esempio

SELECT f.data, f.store, f.tot_fat / h.tot_ore

FROM (*******) as f, (######) as h

WHERE f.store=h.store AND f.data=h.data;

Dovremmo poter scrivere delle query al posto di (*******) e (######)

E’ possibile farlo

SELECT f.data, f.store, f.tot_fat / h.tot_ore

FROM (

SELECT store, data, SUM(importo) as tot_fat

FROM tab_vendite

GROUP BY store, data

) as f,

( SELECT store, data, SUM(ore_lavorate) as tot_ore

FROM tab_ore_lavorate

GROUP BY store, data

) as h

WHERE f.store=h.store AND f.data=h.data;

IN GENERALE

In una query si può utilizzare una sotto-query come se fosse una tabella esistente

SELECT … FROM tab1, tab2, tab3 , tab4 …;

tab3 può essere sostituito da una sotto-query, come nell’esempio seguente:

SELECT … FROM tab1, tab2, ( SELECT …) AS tempTab3 , tab4 …;

• Le parentesi che delimitano la sotto-query sono obbligatorie

• E’ obbligatorio dare un nome ad una sotto-query con l’operatore AS, serve per poter fare riferimento alla

sotto-query in altre parti dell’interrogazione

Query annidate in WHERE

SELECT store, SUM(importo) x IN Y

FROM tab_vendite vero se e solo se l’elemento

WHERE store IN ( x è contenuto nell’insieme Y

SELECT store

FROM tab_ore_lavorate

GROUP BY store

HAVING SUM(ore_lavorate) > 1000

)

GROUP BY store;

La query calcola il fatturato tot dei supermercati in cui sono state impiegate più di 1000 ore dei dipendenti

Altri esempi

• SELECT dipendente FROM tab_ore_lavorate

WHERE store NOT IN (1, 2, 10) AND store IN (

SELECT store

FROM tab_vendite Posso racchiudere i diversi

GROUP BY store valori tra () e separarli da

HAVING SUM(importo)>10’000 virgola

)

GROUP BY dipendente; Modo di rappresentare

• SELECT store, id_cliente, SUM(importo) record con 2 o più

FROM tab_vendite attributi

WHERE (store, id_cliente) NOT IN ((1,24),(1,84))

GROUP BY id_cliente;

SOTTO-QUERY CORRELATE

● SELECT * FROM tab_vendite AS tv x >= ALL (... insieme)

WHERE tv.importo >= ALL vero se x>= … è verificato per tutti gli

( elementi dell’insieme

SELECT importo FROM tab_vendite as tv2

WHERE tv2.id_cliente = tv.id_cliente

);

Questa query visualizza, per ogni cliente, la vendita di importo massimo

Nella (sotto)query,

• la tabella tv non è definita

• si fa quindi riferimento alla tv della query esterna

L’operatore >=

• si aspetta un operando singolo alla sua destra

• Il risultato di una (sotto)query è un insieme

● SELECT * FROM tab_vendite AS tv

WHERE tv.importo >= ALL

( SELECT AVG(importo) FROM tab_vendite as tv2

WHERE tv2.id_cliente = tv.id_cliente

);

Visualizza per ogni cliente, le vendite di importo superiore alla media (delle vendite del singolo cliente)

La query interna produce una sola tupla di risultato

• L’ALL è comunque necessario. L’interprete SQL non può sapere in anticipo quante tuple restituirà la query

annidata

Se mettessi ANY invece che ALL non cambierebbe nulla, SELECT * FROM tab_vendite AS tv

WHERE tv.importo >= ANY

restituirebbe comunque un unico record (

SELECT AVG(importo) FROM tab_vendite as tv2

WHERE tv.id_cliente = tv2.id_cliente

);

ALL, ANY, IN

• sono utilizzati nelle espressioni condizionali

• permettono di confrontare un elemento con un insieme

Sintassi: Elemento OPERATORE {ANY | ALL | IN} Insieme

• Elemento può essere un valore (es. 5) o un attributo

• Operatore può essere un operatore booleano

• Insieme può essere il risultato di una query o un elenco di valori racchiusi tra ()

Esempi (come OPERATORE si utilizzerà il >=)

• x >= ALL (… insieme)

# vero se e solo se la condizione x>= è verificata per

# tutti gli elementi dell’insieme

• x >= ANY (… insieme)

# vero se e solo se la condizione x>= è verificata per

# almeno uno degli elementi dell’insieme

• x IN (… insieme) è equivalente a: x = ANY(… insieme)

• x NOT IN (… insieme) è equivalente a x<>ALL (… insieme)

Efficienza e conversioni

SELECT * SELECT * FROM tab_vendite AS tv, (

FROM tab_vendite AS tv SELECT id_cliente,

WHERE tv.importo >= ALL AVG(importo) as importomedio

( FROM tab_vendite

SELECT AVG(importo) GROUP BY id_cliente

FROM tab_vendite as tv2 ) AS sm

WHERE tv.id_cliente = tv2.id_cliente WHERE tv.id_cliente = sm.id_cliente AND

); tv.importo >= sm.importomedio;

Producono lo stesso risultato.

Sotto-query correlate estremamente inefficienti

• La sotto-query viene rieseguita per ogni record della query esterna

Spesso una sotto-query correlata può essere riscritta in modo più efficiente

Considerazioni

Le sotto-query rendono le interrogazioni inefficienti , va data la preferenza a query senza annidamenti, ma

non sempre è possibile farne a meno.

Le query annidate evitano di dover materializzare i risultati di alcune query. Tuttavia, in alcuni casi può

essere conveniente materializzare se:

• se i dati di partenza sono stabili nel tempo

• i dataset hanno grosse dimensioni

• la computazione delle (sotto)query è molto onerosa

Di volta in volta dovete decidere se è più conveniente materializzare o costruire query annidate

Altri esempi con “where”

Reminder: Tab_vendite (store, id_cliente, data, importo)

Tab_ore_lavorate (store, data, dipendente, ore_lavorate)

● SELECT store, data FROM tab_vendite

WHERE (store, data) NOT IN ( Devo racchiudere store e data tra

SELECT store , data parentesi per far capire che NOT IN

FROM tab_ore_lavorate deve lavorare su entrambi

GROUP BY store, data

HAVING SUM(ore_lavorate) <= 16

)

GROUP BY store, data;

La query individua le coppie <store,data> in cui sono stati impiegati i dipendenti per più di 16 ore giorn.

La clausola IN (e NOT IN) tendono a rallentare il DBMS. Si può riscrivere la query e renderla più veloce?

Equivalenti:

● SELECT store, data FROM tab_vendite

WHERE (store, data) IN (

SELECT store , data FROM tab_ore_lavorate

GROUP BY store, data

HAVING SUM(ore_lavorate) > 16

) GROUP BY store, data;

● SELECT store , data

FROM tab_ore_lavorate Molto meglio delle precedenti

GROUP BY store, data

HAVING

SUM(ore_lavorate) > 16;

Altro esempio

• SELECT store FROM tab_vendite • SELECT store FROM tab_vendite

WHERE store NOT IN ( WHERE store IN (

SELECT store FROM tab_ore_lavorate SELECT store FROM tab_ore_lavorate

GROUP BY store, data GROUP BY store, data

HAVING SUM(ore_lavorate) <= 16 HAVING SUM(ore_lavorate) > 16

) GROUP BY store; ) GROUP BY store;

Non sono equivalenti, Il GROUP BY è necessario per

hanno una diversa granulità le tabelle coinvolte. permettere all’HAVING di lavorare

sulle ore complessive della giornata

JOIN

L'operatore join permette di separare la condizione della clausola where in due parti

• Le condizioni per realizzare il collegamento tra tabelle

• Le condizioni di selezione vere e proprie

Esempio

• SELECT DATAFORNITURA, QT, NOMEPEZZO FROM PEZZI, FORNITURA, FORNITORI

WHERE PEZZI.CODICEPEZZO=FORNITURA.CODICEPEZZO AND

FORNITURA.CODICEFORNITORE=FORNITORI.CODICEFORNITORE AND

FORNITORI.NOMEFORNITORE='giani’ ;

E' equivalente a:

• SELECT DATAFORNITURA, QT, NOMEPEZZO FROM FORNITURA JOIN PEZZI JOIN FORNITORI ON

(PEZZI.CODICEPEZZO=FORNITURA.CODICEPEZZO AND

FORNITURA.CODICEFORNITORE=FORNITORI.CODICEFORNITORE) WHERE

FORNITORI.NOMEFORNITORE='giani’ ;

LEFT (OUTER) JOIN SELECT * FROM proprietari AS p

LEFT JOIN auto AS a ON (p.id_p=a.id_p);

In generale: SELECT * FROM A LEFT JOIN B ON (A.KEY=B.KEY);

Nella tabella risultato entrano:

• Le tuple di A e B che soddisfano la condizione A.KEY=B.KEY L’intersezione rappresenta i record

• Le tuple di A che non soddisfano la condizione A.KEY=B.KEY delle 2 tabelle con chiavi in comune

LEFT excluding (OUTER) JOIN SELECT * FROM proprietari AS p

LEFT JOIN auto AS a ON (p.id_p=a.id_p)

WHERE a.id_p IS NULL;

RIGHT (Outer) JOIN

SELECT * FROM A RIGHT JOIN B ON (A.KEY=B.KEY);

Nella tabella risultato entrano:

• Le tuple di A e B che soddisfano la condizione A.KEY=B.KEY

• Le tuple di B che non soddisfano la condizione A.KEY=B.KEY

RIGHT / - RIGHT Excluding (Outer) JOIN

SELECT * FROM A RIGHT JOIN B ON (A.KEY=B.KEY) WHERE B.KEY IS NULL;

FULL OUTER JOIN

SELECT * FROM A FULL OUTER JOIN B ON (A.KEY=B.KEY);

# In MySQL la sintassi qua sopra non è ammessa

Nella tabella risul

Dettagli
Publisher
A.A. 2018-2019
56 pagine
6 download
SSD Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher aina.belloni di informazioni apprese con la frequenza delle lezioni di Basi di dati e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università degli Studi di Milano - Bicocca o del prof Cesarini Mirko.