Àlgebra relacional
L'àlgebra relacional és el llenguatge formal que Codd va definir el 1970 com a fonament teòric del model relacional. Consisteix en un conjunt d'operadors que prenen una o dues relacions com a entrada i produeixen una nova relació com a sortida. Cada consulta SQL que escrivim es pot expressar —i de fet el motor de BD la compila internament— com una expressió d'àlgebra relacional.
Entendre l'àlgebra relacional ajuda a:
- Comprendre com el SGBD optimitza les consultes (el pla d'execució és un arbre d'operadors).
- Raonar formalment sobre la correcció d'una consulta.
- Entendre per què certes consultes SQL es comporten com es comporten.
Notació
| Símbol | Operador | Entrada |
|---|---|---|
| σ (sigma) | Selecció | Unària |
| π (pi) | Projecció | Unària |
| ρ (rho) | Reanomenament | Unària |
| ∪ | Unió | Binària |
| − | Diferència | Binària |
| × | Producte cartesià | Binària |
| ∩ | Intersecció | Binària (derivada) |
| ⋈ | Join natural | Binària (derivada) |
| ⋈_θ | Theta-join | Binària (derivada) |
| ÷ | Divisió | Binària (derivada) |
Els operadors fonamentals (σ, π, ρ, ∪, −, ×) són suficients per expressar qualsevol consulta. Els derivats (∩, ⋈, ÷) es defineixen a partir dels fonamentals i s'usen per comoditat.
Esquema d'exemple
Al llarg d'aquest document usarem el següent esquema de botiga en línia:
CLIENT(id_client, nom, ciutat, edat)
PRODUCTE(id_producte, descripcio, categoria, preu)
COMANDA(id_comanda, id_client, id_producte, data, quantitat)
Instàncies d'exemple:
CLIENT
| id_client | nom | ciutat | edat |
|---|---|---|---|
| 1 | Anna | Barcelona | 28 |
| 2 | Bernat | Girona | 35 |
| 3 | Carla | Barcelona | 22 |
| 4 | David | Lleida | 41 |
PRODUCTE
| id_producte | descripcio | categoria | preu |
|---|---|---|---|
| P1 | Teclat mecànic | Informàtica | 89.90 |
| P2 | Ratolí ergonòmic | Informàtica | 45.00 |
| P3 | Cadira oficina | Mobiliari | 320.00 |
| P4 | Monitor 27" | Informàtica | 249.00 |
COMANDA
| id_comanda | id_client | id_producte | data | quantitat |
|---|---|---|---|---|
| C1 | 1 | P1 | 2024-01-10 | 1 |
| C2 | 1 | P3 | 2024-01-15 | 2 |
| C3 | 2 | P2 | 2024-02-01 | 1 |
| C4 | 3 | P1 | 2024-02-10 | 3 |
Operadors fonamentals
Selecció (σ)
Filtra les tuples d'una relació que compleixen una condició. El resultat té el mateix esquema que la relació original però potencialment menys tuples.
Sintaxi: σ_condició(R)
Exemple: Clients de Barcelona:
Resultat:
| id_client | nom | ciutat | edat |
|---|---|---|---|
| 1 | Anna | Barcelona | 28 |
| 3 | Carla | Barcelona | 22 |
SQL equivalent:
La condició pot combinar predicats amb els operadors lògics ∧ (AND), ∨ (OR) i ¬ (NOT), i comparadors =, ≠, <, >, ≤, ≥.
Exemple: Clients de Barcelona menors de 30 anys:
Projecció (π)
Selecciona un subconjunt de columnes d'una relació. El resultat té el mateix nombre de tuples però menys atributs. Si al projectar apareixen tuples duplicades, s'eliminen (perquè el resultat és un conjunt).
Sintaxi: π_atributs(R)
Exemple: Noms i ciutats dels clients:
Resultat:
| nom | ciutat |
|---|---|
| Anna | Barcelona |
| Bernat | Girona |
| Carla | Barcelona |
| David | Lleida |
SQL equivalent:
Composició de selecció i projecció: Els operadors es poden combinar. Per obtenir els noms dels clients de Barcelona:
SQL equivalent:
Reanomenament (ρ)
Canvia el nom d'una relació o dels seus atributs. És útil per evitar ambigüitats quan treballem amb dues còpies de la mateixa relació.
Sintaxi: ρ_nouNom(R) o ρ_nouNom(a1→b1, a2→b2)(R)
Exemple: Reanomenar CLIENT com C:
SQL equivalent:
Unió (∪)
Combina les tuples de dues relacions compatibles (mateix nombre d'atributs i dominis compatibles). Elimina duplicats.
Sintaxi: R ∪ S
Exemple: Noms de clients i de ciutats (si volgués una llista unificada de noms):
SQL equivalent:
SELECT nom FROM CLIENT WHERE ciutat = 'Barcelona'
UNION
SELECT nom FROM CLIENT WHERE ciutat = 'Girona';
Compatibilitat de la unió
Dues relacions sóncompatibles per a la unió si tenen el mateix nombre d'atributs i els atributs corresponents tenen dominis compatibles. Els noms dels atributs no cal que coincideixin, però convé reanomenar-los per claredat.
Diferència (−)
Retorna les tuples que estan a la primera relació però no a la segona. Les dues relacions han de ser compatibles per a la unió.
Sintaxi: R − S
Exemple: Clients que no han fet cap comanda:
Resultat: {4} (David no té cap comanda)
SQL equivalent:
Producte cartesià (×)
Combina cada tupla de R amb cada tupla de S. Si R té m tuples i n atributs, i S té p tuples i q atributs, el resultat té m×p tuples i n+q atributs.
Sintaxi: R × S
Exemple:
Produeix totes les combinacions possibles de clients i productes (4 × 4 = 16 tuples). Per si sol no és gaire útil; s'usa combinat amb la selecció per implementar el join.
SQL equivalent:
Operadors derivats
Intersecció (∩)
Retorna les tuples que estan en totes dues relacions. Es pot expressar amb la diferència:
Exemple: Clients que han comprat tant el producte P1 com el P2:
SQL equivalent:
SELECT id_client FROM COMANDA WHERE id_producte = 'P1'
INTERSECT
SELECT id_client FROM COMANDA WHERE id_producte = 'P2';
Theta-join (⋈_θ)
Combina dues relacions seleccionant les parelles de tuples que compleixen una condició θ. Es defineix com:
Exemple: Clients amb les seves comandes (condició d'igualtat):
SQL equivalent:
Equijoin
Theta-join on la condició θ és una igualtat (=). El resultat conté les dues columnes de la condició (la de R i la de S).
Join natural (⋈)
Un equijoin que fa la igualtat automàticament sobre tots els atributs amb el mateix nom, i elimina les columnes duplicades del resultat.
El join es fa sobre id_client (l'únic atribut comú) i el resultat té id_client una sola vegada.
SQL equivalent:
Precaució amb el join natural
El join natural pot donar resultats inesperats si dues taules comparteixen per coincidència un nom d'atribut que no és una FK/PK. A la pràctica s'usa l'equijoin explícit o la sintaxi USING.
Divisió (÷)
L'operador de divisió és el menys intuïtiu però és molt útil per a consultes del tipus "quins X han fet tots els Y". Si R(A, B) i S(B), llavors R ÷ S retorna els valors de A que apareixen a R associats a tots els valors de B que hi ha a S.
Sintaxi: R ÷ S
Exemple: Quin clients han comprat tots els productes d'Informàtica?
Comprades = π_id_client, id_producte(COMANDA)
Informatica = π_id_producte(σ_categoria='Informàtica'(PRODUCTE))
Comprades ÷ Informatica
SQL equivalent (usant doble negació):
SELECT DISTINCT id_client FROM COMANDA c1
WHERE NOT EXISTS (
SELECT id_producte FROM PRODUCTE
WHERE categoria = 'Informàtica'
AND id_producte NOT IN (
SELECT id_producte FROM COMANDA c2
WHERE c2.id_client = c1.id_client
)
);
La divisió es pot expressar amb els operadors fonamentals:
Equivalències àlgebra relacional ↔ SQL
| Àlgebra relacional | SQL |
|---|---|
| σ_condició(R) | WHERE condició |
| π_a1,a2(R) | SELECT DISTINCT a1, a2 |
| R ∪ S | UNION |
| R − S | EXCEPT / MINUS |
| R ∩ S | INTERSECT |
| R × S | CROSS JOIN |
| R ⋈_θ S | JOIN ... ON θ |
| R ⋈ S | NATURAL JOIN |
| ρ_nou(R) | AS nou |
Propietats dels operadors
Conèixer les propietats permet l'optimització algebraica: el SGBD reescriu la consulta en una forma equivalent però més eficient.
Commutativitat
- R ∪ S = S ∪ R
- R ∩ S = S ∩ R
- R ⋈ S = S ⋈ R
- R × S ≠ S × R (el resultat és equivalent però l'ordre de les columnes canvia)
Associativitat
- (R ∪ S) ∪ T = R ∪ (S ∪ T)
- (R ⋈ S) ⋈ T = R ⋈ (S ⋈ T)
Regla de cascada de seleccions
Una selecció conjuntiva es pot descompondre:
Això permet baixar les seleccions a prop de les fulles de l'arbre per reduir el nombre de tuples el més aviat possible.
Conmutació selecció-producte cartesià
Si la condició c només afecta atributs de R:
Aquesta és la transformació que converteix un producte cartesià + selecció en un join: el SGBD aplica primer el filtre i redueix R abans de fer el producte.
Arbres d'operadors
Les expressions d'àlgebra relacional es representen com a arbres, on:
- Les fulles són les relacions base.
- Els nodes interns són els operadors.
- L'arrel és el resultat final.
Exemple: Noms dels clients de Barcelona que han fet almenys una comanda:
El SGBD pot reordenar l'arbre per optimitzar:
Aplicant primer la selecció a CLIENT reduïm el nombre de tuples que participen al join.
Exercicis
Usa l'esquema d'exemple (CLIENT, PRODUCTE, COMANDA) per expressar les consultes següents en àlgebra relacional i, després, en SQL:
- Llista els noms dels clients majors de 30 anys.
- Quins productes costen menys de 100 EUR?
- Obté les comandes realitzades per la client Anna.
- Llista les categories de productes que han estat comprats (sense repeticions).
- Quins clients han fet almenys una comanda de més de 2 unitats?
- Llista els noms dels clients que no han fet cap comanda.
- Quins clients han comprat productes de totes les categories?
Ordre recomanat
Per resoldre una consulta en àlgebra relacional, convé seguir aquest ordre: (1) identifica les taules que necessites, (2) aplica les seleccions per filtrar files, (3) fes els joins necessaris, (4) projecta les columnes que vols al resultat.