Esercizio - Algebra relazionale su impiegati e dirigenti (esercizi di algebra relazionale del corso)
In questa pagina 11
Testo (esercizi di algebra relazionale del corso di Basi di Dati, Ing. Informatica UniPD). Dato lo schema
Employee(Badge, Surname, Age, Salary), chiaveBadge;Manage(Employee, Manager), chiaveEmployee, conEmployeeeManagerchiavi esterne versoEmployee.Badge(a ogni impiegato corrisponde al più un dirigente)
e l'istanza
| Employee: Badge | Surname | Age | Salary |
|---|---|---|---|
| 7309 | Rossi | 34 | 45 |
| 5998 | Bianchi | 37 | 38 |
| 9553 | Neri | 42 | 35 |
| 5698 | Bruni | 43 | 42 |
| 4076 | Mori | 45 | 50 |
| 8123 | Lupi | 46 | 60 |
| Manage: Employee | Manager |
|---|---|
| 7309 | 5698 |
| 5998 | 5698 |
| 9553 | 4076 |
| 5698 | 4076 |
| 4076 | 8123 |
scrivere in algebra relazionale:
- badge, cognome, età e stipendio degli impiegati che guadagnano più di 42;
- badge, cognome ed età degli impiegati che guadagnano più di 42;
- il badge dei dirigenti i cui impiegati guadagnano più di 42;
- cognome e stipendio dei dirigenti i cui impiegati guadagnano più di 42;
- cognome e stipendio dei dirigenti che guadagnano più di 45;
- gli impiegati che guadagnano più del proprio dirigente, con badge, cognome e stipendio di entrambi;
- il badge dei dirigenti i cui impiegati guadagnano tutti più di 42;
- il badge dei dirigenti che a loro volta hanno un dirigente.
Teoria: Algebra relazionale - operatori di base e joinLe operazioni sul modello relazionale sono di aggiornamento (inserimento, modifica, cancellazione, che possono violare i vincoli di integrità: si rifiuta, si corregge, si propaga con cascade o si imposta NULL/default) e di interrogazione (funzioni che da un'istanza del database producono una relazione). L'algebra relazionale è il linguaggio procedurale delle interrogazioni: gli operatori primitivi sono unione, differenza, prodotto, rinomina ρ, selezione σ e proiezione π; derivati sono intersezione, theta-join, equi-join, join naturale. Unione, intersezione e differenza richiedono relazioni compatibili all'unione (stessi attributi e domini). La selezione è una decomposizione orizzontale, la proiezione verticale (commutano solo se gli attributi della selezione sono nella proiezione). Il theta-join è σ_φ(R1×R2), il join naturale equivale a un equi-join sugli attributi omonimi seguito da una proiezione; la sua cardinalità è tra 0 e |R1||R2|, ≤|R1| se gli attributi comuni sono chiave di R2, =|R1| se sono anche chiave esterna di R1 con vincolo di integrità referenziale. Le tuple senza corrispondente sono "dangling". I valori NULL richiedono condizioni esplicite IS NULL / IS NOT NULL, perché σ_{A>40} ∪ σ_{A≤40} non restituisce le tuple con A nullo.Algebra relazionale - operatori di base e join →. Estensioni: Algebra relazionale estesa - divisione, aggregazione e outer joinL'algebra relazionale di base lavora una tupla alla volta e non sa fare calcoli sui valori né riassumere più tuple. L'estensione aggiunge: la proiezione generalizzata π_{F1,...,Fn}(R), che calcola espressioni sugli attributi (prezzo per quantità); l'aggregazione ℱ_{SUM, MAX, MIN, AVG, COUNT}(R), che produce una sola tupla; il raggruppamento (A1,...,Am)ℱ_{f(B)}(R), che produce una tupla per gruppo (grado n+m, cardinalità = numero di gruppi). Le funzioni di aggregazione ignorano i NULL, COUNT(*) conta le tuple, i NULL formano un gruppo a sé. Gli outer join (left, right, full) mantengono con NULL le tuple dangling del join; i NULL nella chiave di join non si accoppiano mai. La divisione R÷S dà gli x tali che (x,y) sta in R per ogni y di S, e si ottiene con π, × e −. Ricette: massimo = aggregazione + join con il massimo, "tutti" = divisione o complemento, "almeno due" = self-join.Algebra relazionale estesa - divisione, aggregazione e outer join →. Ogni espressione è stata valutata con un piccolo interprete di algebra su queste tabelle e confrontata con l'equivalente SQL provato con SQLite: i risultati sotto coincidono.
Esercizio 1
Una selezione basta: si tengono le tuple con , schema invariato.
| Badge | Surname | Age | Salary |
|---|---|---|---|
| 7309 | Rossi | 34 | 45 |
| 4076 | Mori | 45 | 50 |
| 8123 | Lupi | 46 | 60 |
(Bruni guadagna esattamente 42: non è "più di 42".) SQL: SELECT * FROM Employee WHERE Salary > 42;. È una decomposizione orizzontale: si sceglie un sottoinsieme di righe.
Esercizio 2
Si aggiunge una proiezione: si scelgono le colonne. Si valuta dall'interno, prima la selezione.
| Badge | Surname | Age |
|---|---|---|
| 7309 | Rossi | 34 |
| 4076 | Mori | 45 |
| 8123 | Lupi | 46 |
Perché l'ordine conta. Se si proietta per primi, non ha più Salary, e non si può applicare: errore. Selezione e proiezione commutano solo se gli attributi della selezione sono tra quelli proiettati (qui non lo sono).
Esercizio 3
Il dirigente sta in Manage, lo stipendio dell'impiegato in Employee: serve un join tra Employee = Badge. Conviene prima selezionare gli impiegati ricchi (relazione piccola) e poi fare il join:
Passi:
- : Rossi (7309), Mori (4076), Lupi (8123);
- il join con
Managetiene le tuple diManageil cuiEmployeeè uno di questi badge: e . L'impiegato 8123 non compare inManage.Employee(è il vertice): non ha corrispondente, la sua tupla diEmployeeè dangling e sparisce. È l'approccio basato sui valori del modello relazionale: ci si collega solo uguagliando valori; - dà .
| Manager |
|---|
| 5698 |
| 8123 |
Si può fare prima il join e poi la selezione (stesso risultato), ma il join lavora su più tuple: meno efficiente. Per il join è un equi-join, non un join naturale: gli attributi hanno nomi diversi (Employee e Badge). SQL:
SELECT DISTINCT Manager
FROM Manage m JOIN Employee e ON m.Employee = e.Badge
WHERE e.Salary > 42;Il DISTINCT corrisponde al fatto che la proiezione algebrica elimina i duplicati (un dirigente con due impiegati ricchi comparirebbe due volte).
Esercizio 4
Ora servono i dati del dirigente (cognome, stipendio): ci vuole un secondo join con Employee, che va però rinominata per non confondere l'impiegato con il dirigente.
Soluzione 1 (la prima del corso). Si rinomina la selezione sugli impiegati ricchi:
contiene e (due tuple: le coppie dirigente-impiegato ricco). abbina a ciascuna il dirigente (Badge = Manager): Bruni (5698) e Lupi (8123). Il risultato:
| Surname | Salary |
|---|---|
| Bruni | 42 |
| Lupi | 60 |
Soluzione 2 (equivalente, più corta, per eliminare la rinomina): si riusa il risultato dell'esercizio 3, che contiene già solo i badge dei dirigenti,
Nessuna rinomina è necessaria perché Manager e Badge sono nomi diversi e la parte interna ha solo l'attributo Manager. È il consiglio generale: si proietta via ciò che non serve appena possibile. SQL:
SELECT DISTINCT m.Surname, m.Salary
FROM Employee m JOIN Manage g ON g.Manager = m.Badge
JOIN Employee e ON e.Badge = g.Employee
WHERE e.Salary > 42;Qui compaiono due volte Employee con alias m (manager) ed e (impiegato): in SQL la rinomina è l'alias.
Esercizio 5
Chiede i dirigenti con stipendio : si seleziona su Employee come dirigente e si collega con Manage.Manager.
- : Mori (50) e Lupi (60);
- il join con
ManagesuManager = Badgedà tre tuple: , , : Mori compare due volte perché ha due impiegati (approccio basato sui valori: ogni corrispondenza genera una tupla); - la proiezione su rende uguali le due tuple di Mori e, essendo una relazione un insieme, ne resta una.
| Surname | Salary |
|---|---|
| Mori | 50 |
| Lupi | 60 |
Il join con Manage serve a restringere ai soli dirigenti: da sola contiene chiunque guadagni più di 45, anche chi non dirige nessuno (nei dati dati sono tutti dirigenti, ma in generale no). Qui non servono i dati degli impiegati, solo la loro esistenza come "dirigente di qualcuno": a differenza dell'esercizio 4, quindi, non serve alcuna rinomina. SQL: SELECT DISTINCT e.Surname, e.Salary FROM Manage m JOIN Employee e ON m.Manager = e.Badge WHERE e.Salary > 45;.
Esercizio 6
Servono due copie di Employee (impiegato e dirigente) e un confronto tra i loro stipendi: un self-join con rinomina e un theta-join (la condizione non è un'uguaglianza).
Soluzione 1 (equi-join e poi selezione):
Soluzione 2 (theta-join, evita la selezione dopo l'equi-join):
Passi: il primo join associa a ogni impiegato la riga di Manage (5 tuple); il secondo aggancia a ogni riga il dirigente (la copia rinominata), e la condizione tiene le coppie in cui l'impiegato guadagna più del dirigente. Le cinque coppie (impiegato con stipendio, dirigente con stipendio) sono: Rossi 45 e Bruni 42 (sì), Bianchi 38 e Bruni 42, Neri 35 e Mori 50, Bruni 42 e Mori 50, Mori 50 e Lupi 60 (no, in tutti gli altri casi). Unico risultato:
| Badge | Surname | Salary | M.Bdg | M.Srn | M.Slry |
|---|---|---|---|---|---|
| 7309 | Rossi | 45 | 5698 | Bruni | 42 |
SQL:
SELECT e.Badge, e.Surname, e.Salary, m.Badge, m.Surname, m.Salary
FROM Manage g JOIN Employee e ON g.Employee = e.Badge
JOIN Employee m ON g.Manager = m.Badge
WHERE e.Salary > m.Salary;Esercizio 7
"Tutti gli impiegati guadagnano più di 42" è una condizione universale: l'algebra non ha il , ma si usa il complemento: tutti i dirigenti meno quelli per cui esiste un impiegato con stipendio (il contrario di "" è "").
- : tutti i dirigenti;
- : Bianchi (38), Neri (35), Bruni (42);
- il join con
Managedà le coppie , , , la cui proiezione suManagerè : i dirigenti con almeno un impiegato "povero"; - la differenza lascia : Lupi dirige solo Mori (50).
| Manager |
|---|
| 8123 |
Un errore tipico è dimenticare che la prima parte deve essere "i dirigenti" e non tutti gli impiegati: un impiegato che non dirige nessuno soddisfarebbe vacuamente il "tutti". SQL con EXCEPT: SELECT DISTINCT Manager FROM Manage EXCEPT SELECT m.Manager FROM Manage m JOIN Employee e ON m.Employee = e.Badge WHERE e.Salary <= 42;.
Esercizio 8
Un dirigente che a sua volta ha un dirigente è un badge che compare sia come Manager sia come Employee in Manage.
Soluzione 1 (self-join con rinomina). Si accoppia Manage con una sua copia, dove l'impiegato della copia deve coincidere con il dirigente della prima; la copia va rinominata per intero (anche Manager, altrimenti ci sarebbero due attributi con lo stesso nome):
Le tuple che si accoppiano sono quelle in cui il dirigente della prima è impiegato della seconda: 5698 (è impiegato con dirigente 4076) e 4076 (con dirigente 8123). Il risultato .
Soluzione 2 (intersezione di due proiezioni, rese compatibili con la rinomina):
I dirigenti intersecati con gli impiegati danno . È la forma più leggibile.
| WithMgr |
|---|
| 4076 |
| 5698 |
Errore da evitare: . Confronta i due attributi nella stessa tupla, cioè cerca chi dirige se stesso, e restituisce la relazione vuota (verificato). Il collegamento tra "il dirigente di una riga" e "l'impiegato di un'altra riga" richiede un join della relazione con una sua copia.
SQL: SELECT DISTINCT a.Manager FROM Manage a JOIN Manage b ON a.Manager = b.Employee;.
Altri esercizi sullo stesso schema
9. I badge degli impiegati che non hanno un dirigente (nessuno li dirige). "Che non" = differenza:
10. I dirigenti con almeno due impiegati. Self-join di Manage con la copia rinominata e la condizione sugli impiegati diversi:
(Con l'algebra estesa: si raggruppa Manage per Manager, si conta e si tengono i gruppi con conteggio almeno 2.)
11. Stipendio medio degli impiegati di ciascun dirigente (algebra estesa): dà , , (verificato anche in SQL con GROUP BY Manager).
12. L'impiegato con lo stipendio massimo. e .
Valori nulli e outer join: un esempio
Con Employee(Badge, Surname, Age, Branch) = , , : dà Bianchi, dà Rossi, e la loro unione non è la relazione di partenza: Neri manca. Per recuperarla si aggiunge . Con Employee(Surname, Dep) e Department(Code, Manager) della nota di teoria, il full outer join aggiunge a 3 tuple di join le tuple dangling e : 5 tuple in tutto, come visto in Algebra relazionale estesa - divisione, aggregazione e outer joinL'algebra relazionale di base lavora una tupla alla volta e non sa fare calcoli sui valori né riassumere più tuple. L'estensione aggiunge: la proiezione generalizzata π_{F1,...,Fn}(R), che calcola espressioni sugli attributi (prezzo per quantità); l'aggregazione ℱ_{SUM, MAX, MIN, AVG, COUNT}(R), che produce una sola tupla; il raggruppamento (A1,...,Am)ℱ_{f(B)}(R), che produce una tupla per gruppo (grado n+m, cardinalità = numero di gruppi). Le funzioni di aggregazione ignorano i NULL, COUNT(*) conta le tuple, i NULL formano un gruppo a sé. Gli outer join (left, right, full) mantengono con NULL le tuple dangling del join; i NULL nella chiave di join non si accoppiano mai. La divisione R÷S dà gli x tali che (x,y) sta in R per ogni y di S, e si ottiene con π, × e −. Ricette: massimo = aggregazione + join con il massimo, "tutti" = divisione o complemento, "almeno due" = self-join.Algebra relazionale estesa - divisione, aggregazione e outer join →.
Errori nel materiale del corso
- Nella scheda a mano la riga di Mori compare con stipendio 60 in alcune tabelle intermedie degli esercizi 3 e 4 (per esempio nel passo ""), mentre nella tabella
Employeevale 50: è un refuso di trascrizione. I risultati finali non cambiano. Nello stesso passo, un'etichetta riporta invece di . - Nella soluzione 1 dell'esercizio 8 (slide sull'algebra) la rinomina lascia due attributi chiamati
Managernel join (quello diManagee quello della copia): la scheda annota "Manager dovrebbe essere rinominato insieme a Employee, ma...". Va rinominata anche la seconda colonna, come qui sopra.
Versione ripasso
Schema: Employee(Badge, Surname, Age, Salary) e Manage(Employee, Manager), entrambi con badge. Teoria: Algebra relazionale - operatori di base e joinLe operazioni sul modello relazionale sono di aggiornamento (inserimento, modifica, cancellazione, che possono violare i vincoli di integrità: si rifiuta, si corregge, si propaga con cascade o si imposta NULL/default) e di interrogazione (funzioni che da un'istanza del database producono una relazione). L'algebra relazionale è il linguaggio procedurale delle interrogazioni: gli operatori primitivi sono unione, differenza, prodotto, rinomina ρ, selezione σ e proiezione π; derivati sono intersezione, theta-join, equi-join, join naturale. Unione, intersezione e differenza richiedono relazioni compatibili all'unione (stessi attributi e domini). La selezione è una decomposizione orizzontale, la proiezione verticale (commutano solo se gli attributi della selezione sono nella proiezione). Il theta-join è σ_φ(R1×R2), il join naturale equivale a un equi-join sugli attributi omonimi seguito da una proiezione; la sua cardinalità è tra 0 e |R1||R2|, ≤|R1| se gli attributi comuni sono chiave di R2, =|R1| se sono anche chiave esterna di R1 con vincolo di integrità referenziale. Le tuple senza corrispondente sono "dangling". I valori NULL richiedono condizioni esplicite IS NULL / IS NOT NULL, perché σ_{A>40} ∪ σ_{A≤40} non restituisce le tuple con A nullo.Algebra relazionale - operatori di base e join →, Algebra relazionale estesa - divisione, aggregazione e outer joinL'algebra relazionale di base lavora una tupla alla volta e non sa fare calcoli sui valori né riassumere più tuple. L'estensione aggiunge: la proiezione generalizzata π_{F1,...,Fn}(R), che calcola espressioni sugli attributi (prezzo per quantità); l'aggregazione ℱ_{SUM, MAX, MIN, AVG, COUNT}(R), che produce una sola tupla; il raggruppamento (A1,...,Am)ℱ_{f(B)}(R), che produce una tupla per gruppo (grado n+m, cardinalità = numero di gruppi). Le funzioni di aggregazione ignorano i NULL, COUNT(*) conta le tuple, i NULL formano un gruppo a sé. Gli outer join (left, right, full) mantengono con NULL le tuple dangling del join; i NULL nella chiave di join non si accoppiano mai. La divisione R÷S dà gli x tali che (x,y) sta in R per ogni y di S, e si ottiene con π, × e −. Ricette: massimo = aggregazione + join con il massimo, "tutti" = divisione o complemento, "almeno due" = self-join.Algebra relazionale estesa - divisione, aggregazione e outer join →.
- : Rossi (7309), Mori (4076), Lupi (8123). Bruni guadagna 42, quindi è escluso.
- . L'ordine conta: proiettando prima,
Salarynon esiste più. - . È un equi-join, non naturale, perché i nomi sono diversi. Lupi (8123) non compare in
Manage.Employee: la sua tupla è dangling.- SQL:
SELECT DISTINCT Manager FROM Manage m JOIN Employee e ON m.Employee = e.Badge WHERE e.Salary > 42;
- SQL:
- Cognome e stipendio dei dirigenti: . Per riusare il risultato del punto 3 non serve una rinomina. Nella versione con la copia rinominata la rinomina è obbligatoria.
- . Il join dà tre tuple, con Mori due volte perché ha due impiegati; la proiezione ne lascia una. Il join serve a restringere ai soli dirigenti, quindi non serve alcuna rinomina.
- Impiegati che guadagnano più del loro dirigente. Servono due copie di
Employee, quindi self-join con e theta-join: Il primo join dà 5 tuple, il secondo tiene le coppie con stipendio maggiore. Unico risultato: (7309, Rossi, 45, 5698, Bruni, 42). - Dirigenti i cui impiegati guadagnano tutti più di 42. Si usa il complemento, perché l'algebra non ha il : tutti i dirigenti meno quelli con un impiegato .
Il sottraendo è : Bianchi (38) e Neri (35) sono sotto soglia. Lupi dirige solo Mori (50).
- SQL con
EXCEPT:SELECT DISTINCT Manager FROM Manage EXCEPT SELECT m.Manager FROM Manage m JOIN Employee e ON m.Employee = e.Badge WHERE e.Salary <= 42;
- SQL con
- Dirigenti che hanno a loro volta un dirigente: un badge che compare sia come
Managersia comeEmployee. Equivale al self-join con rinomina di entrambe le colonne della copia.- Errore: è vuota, perché confronta due attributi della stessa tupla.
Altri esercizi sullo stesso schema
- Impiegati senza dirigente: .
- Dirigenti con almeno due impiegati: self-join con , risultato .
- Stipendio medio per dirigente: , , .
Errori tipici
- Rinominare una sola colonna nel self-join.
- Selezionare dopo aver proiettato via l'attributo.
- Dimenticare che il join perde le tuple dangling.