256 lines
9.2 KiB
Markdown
256 lines
9.2 KiB
Markdown
---
|
|
title: "Base de données avancées : Algèbre relationnelle"
|
|
date: 2022-01-12
|
|
tags: ["schema", "algèbre relationnelle", "relation"]
|
|
categories: ["Base de données avancées", "Cours"]
|
|
mathjax: true
|
|
---
|
|
|
|
L'agèbre relationnelle est un langage de requêtes dans une base de donnée
|
|
relationelle. Inventé par Edgar F. Codd en 1970, il représente le fondement
|
|
théorique du langage SQL.
|
|
|
|
|
|
C'est un langage procédural : les requêtes sont des suites d'opérations qui
|
|
construise la réponse.Il permet la manipulation des relations par interrogation
|
|
en combiant les relations avec différents opérateurs afin d'obtenir de nouvelles
|
|
relations.
|
|
|
|
## La projection
|
|
|
|
La projection permet de ne garder que les *n_uplets* des attibuts indiqué par
|
|
l'opérateur en supprimant les éventuels doublons. Il est noté \\(\pi\\), son
|
|
équivalent SQL est `SELECT`. On parle alors de *partition verticale*
|
|
|
|
* Soit \\(R(\underline{A,B},C,D)\\)
|
|
* La projection des attibuts C et D donne \\(\pi_D(R) = R'(C,D)\\)
|
|
|
|
## La selection
|
|
|
|
L'opérateur de selection (ou restriction) ne permet de retenir que *n_uplets*
|
|
vérifiant une condition particulière donnée sous forme de prédicat[^n_predicat].
|
|
Il est noté \\(\sigma\\)) et équivaut à la clause `WHERE` en SQL.
|
|
|
|
* Soit \\(R(\underline{A,B},C,D)\\)
|
|
* la selection \\(\sigma_{C>2}(R) = R'(A,B,C,D)\\) sélection les ligne de la
|
|
relation \\(R\\) dont \\(C\\) est supérieur à 2
|
|
|
|
Les opérateurs possibles sont \\(>, <, \geqslant, \leqslant, =, \ne, \subset,
|
|
\subseteq, \nsubseteq \\)
|
|
|
|
Utilisons les relations de notre exemple de la compagne aérienne, pour trouver
|
|
les numéros de séries des avions avec une capacité supérieure à 150 passagers.
|
|
|
|
\\( \pi_{\text{num_serie}}(\sigma_{capacité > 150}(avions)) \\)
|
|
|
|
|
|
[^n_predicat]:propriété des objets du langage exprimée dans le langage en
|
|
question (source [Wikipédia](https://fr.wikipedia.org/wiki/Pr%C3%A9dicat))
|
|
|
|
## jointure
|
|
|
|
La jointure (ou jointure naturelle) rapproche deux relations liées par des
|
|
attributs communs. Les *n_uplets* du résultat sont obtenus par concaténation des
|
|
attributs des deux relations lorsque les attributs communs ont des valeurs
|
|
identiques. La jointure est notée \bowtie, son équivalent au `JOIN` en SQL.
|
|
|
|
* soit deux relations \\( conso(plat, client) \\) et \\( client(id, nom,
|
|
prénom) \\)
|
|
* \\( \pi_{nom, prénom}(\sigma_{plat = donuts}(conso \bowtie_{conso.client =
|
|
client.id} client)) \\) donne les clients ayant commandé des donuts.
|
|
|
|
## auto-jointure
|
|
|
|
L'auto-jointure est la jointure d'une table sur elle-même. elle permet, par
|
|
exemple, de calculer une hiérarchie. Lors de l'utilisation de cet operateur, il
|
|
faut renommer chaque relation qui compose la jointure de façon unique. Cet
|
|
|
|
l'opérateur \\( \rho \\) permet de renommer une relation le temps d'une requête.
|
|
|
|
* soit une relation \\( employés(matricule, nom, prénom, supérieur) \\)
|
|
* \\( \pi_{D}(\sigma_{nom = Simpson}((employés \bowtie_{employés.matricule = s.D}
|
|
(\rho{s(A,B,C,D}(employés))) \\) permet de trouver le superieur
|
|
hiérarchique de Simpson.
|
|
|
|
## Opérations binaires
|
|
|
|
Les opérations binaires sont des opérations mathématiques standard de la
|
|
théories des ensembles. Elles ne peuvent s'appliquer **que sur des relations
|
|
compatibles**. On y trouve
|
|
|
|
* Union
|
|
* Intersection
|
|
* Différence
|
|
* Division
|
|
|
|
Pour deux relations \\(A(A_1, A_2, A_3, ..., A_n)\\) et \\(B(B_1, B_2, B_3, ...,
|
|
B_n\\) sont **compatibles** si et seulement si elles ont le même degrès
|
|
[^n_degres] et si \\(dom(A_i) = dom(B_i)\\) pour \\(1 \leqslant i \leqslant n
|
|
\\)
|
|
|
|
[^n_degres]:le degrés représente le nombre d'attributs d'une relation
|
|
|
|
### Union
|
|
|
|
\\(A \cup B\\) est une relation qui inclue tous les *n_uplets* qui
|
|
appartiennent à A, B ou au deux. Les doublons sont éliminés.
|
|
|
|

|
|
|
|
### Intersection
|
|
|
|
\\( A \cap B \\) est une relation qui inclue les *n_uplets* appartenant à A et à
|
|
B et seulement ceux-ci.
|
|
|
|

|
|
|
|
### Différence
|
|
|
|
\\( A - B \\) est une relation qui inclue tous les *n_uplets* appartenant à A
|
|
mais pas à B.
|
|
|
|

|
|
|
|
Elle répond à la question quel sont les A qui n'ont aucun B.
|
|
|
|
### Division
|
|
|
|
La division permet de conserver une sous ensemble de *n_uplets* partie de
|
|
\\(R\\) qui sont tous présent dans \\(S\\). Elle permet de répondre à des
|
|
questions du type *quel est le truc qui a tous les machins?*.
|
|
|
|
Pour l'exemple, reprenons notre base de donnée de la compagnie aérienne du
|
|
chapitre précédent.
|
|
|
|

|
|
|
|
Utilisons la division pour répondre à la question "Quels commandants ont volé
|
|
sur tous les type d'avion:
|
|
|
|
\\[
|
|
\Pi_{matricule, type}(
|
|
pilotes \underset{pilotes.matricule = planning.matricule}{\bowtie}
|
|
planning \underset{\text{planning.num_avion} = \text{avions.num_serie}}{\bowtie}
|
|
avions)
|
|
\div \Pi_{type}(avion)
|
|
\\]
|
|
|
|
## Calcul relationnel
|
|
|
|
Le calcul relationnel est un langage formel permettant, tout comme l'algèbre
|
|
relationnel, d'exprimer des requêtes afin d'interroger des base de données
|
|
relationnelles.
|
|
|
|
Les requêtes se présentent sous la forme \\({t|P(t)}\\), elle représente
|
|
l'ensemble des *n_uplets* tel que le prédicat \\(P(t)\\) est vrai pour \\(t\\).
|
|
|
|
\\(t\\) est une variable de *n_uplet* et \\(t[A]\\) représente la valeur de
|
|
l'attribut \\(A\\) dans \\(t\\). \\(t \in r\\) signifie que \\(t\\) est un
|
|
*n_uplet* de \\(r\\).
|
|
|
|
Il existe aussi les connecteur logiques :
|
|
* \\(\lor\\) : **ou** logique
|
|
* \\((\land\\) : **et** logique
|
|
* \\(\neg\\) : la négation
|
|
|
|
Mais aussi des quantificateurs :
|
|
* \\(\exists\\) : **il existe**, par exemple \\(\exists t \in r(Q(t))\\) il
|
|
existe un tuple t de r tel que Q est vrai.
|
|
* \\(\forall\\) : **pour tout**, par exemple \\(\forall t \in r(Q(t))\\) - Q
|
|
est vrai pour tout tuple t de r.
|
|
* \\(\nexists\\) : **il n'existe pas**, par exemple \\(\nexists t \in
|
|
r(Q(t))\\) - il n'existe pas de tuple t dans r tel que Q est vrai.
|
|
|
|
### Un exemple concret : base de donnée cinéma
|
|
|
|
Essayons d'éclaicir tout celà à l'aide d'un exemple concret, considérons les
|
|
relations suivantes:
|
|
|
|
* Films(titre, realisateur, Acteur) instance f
|
|
* Programme(nom_cinemas, titre, horaire) instance p
|
|
|
|
#### les films réalisés par Terry Gilliam
|
|
|
|
\\( \\{ t | t \in f \land t[realisateur] = "\text{Terry Gilliam"} \\} \\)
|
|
|
|
#### les films ou jouent Jay et Silent Bob
|
|
|
|
\\( \\{ t | t \in f \land \exists s \in f( t[titre] = s[titre] \land
|
|
t[acteur] = "Jay" \land s[acteur] = "Silent Bob" ) \\} \\)
|
|
|
|
#### tous les films programmés dans toutes les salles
|
|
|
|
\\( \\{ t | \exists s \in p(t[titre] = s[titre]) \\} \\)
|
|
|
|
#### Les films programmés à l'UGC mais pas au Megarama
|
|
|
|
\\( \\{
|
|
t | \exists s \in p(s[titre] = t[titre]
|
|
\land s[\text{nom_cinemas}] = "UCG"
|
|
\land {\neg} {\exists} u \in p( u[\text{nom_cinemas}] = "Megarama"
|
|
\land u[titre] = t[titre]
|
|
\\} \\)
|
|
|
|
#### Les titres des films qui sont passés à l'UGC et leurs réalisateurs
|
|
|
|
\\( \\{
|
|
t | \exists \in p(\exists u \in f((s[\text{nom_cinemas}] = "UGC"
|
|
\land s[titre] = u[titre] = t[titre]
|
|
\land t[realisateur] = u[realisateur]
|
|
\\} \\)
|
|
|
|
### Retour sur la notion de clé
|
|
|
|
comme nous lavons abordé précédement, une clé est nécessaire pour identifier des
|
|
*n_uplets* de façon unique sans pour autant en donner toutes leurs valeurs et
|
|
respecter leurs unicité.
|
|
|
|
Plus formellement
|
|
|
|
* \\(X \text{ clé de } R(U) \textit{ avec } X \subseteq U \textit{ ssi } \forall
|
|
r:R(U) \\)
|
|
* \\(\forall t_1, t_2 \in r \\)
|
|
* \\(t_1\[X\] = t_2\[X\] \implies t_1 = t_2 \\)
|
|
* \\(\neg \exists Y \subset X \implies t_1[Y] = t_2[Y] \implies t_1 = t_2\\)
|
|
|
|
### Expression saine
|
|
|
|
Il est possible d'écrire en calcul algébrique des requêtes qui retourne un
|
|
relation infinie. Un exemple parlant avec les numéros de comptes :
|
|
|
|
* Soit \\(Numcompte(Num)\\)) avec l'instance \\(n\\)
|
|
* Et la requête \\(\\{ t | \neg t \in n \\}\\) représentant les numéros de
|
|
comptes non rencencés.
|
|
* si on considère que \\( Dom(Num) = IN \\) alors la réponse à la question est
|
|
infinie.
|
|
|
|
Un requête est saine si **quel que soit l'instance de la base** dans laquelle on
|
|
l'évalue, elle retourne **une réponse finie**.
|
|
|
|
## Calcul relationnel par domaine
|
|
|
|
Le calcul relationnel par domaine est un langage de requête non procédural. Il
|
|
ne fournit que la description de la requête et pas les méthodes pour la
|
|
résoudre. Elle prend la forme suivante:
|
|
|
|
\\(\\{ < x_1, x_2, ... , x_n> | P(x_1, x_2, ... , x_n)\\}\\)
|
|
|
|
* \\(< x_1, x_2, ... , x_n>\\) représente les variables de domaine résultant
|
|
* \\(P(x_1, x_2, ... , x_n)\\}\\) représente la formule similaire à ce que l'on
|
|
trouve dans la logique des prédicats
|
|
|
|
Si on reprends notre exemple des cinémas, la requête permettant de trouver les
|
|
films proposé à l'UGC est
|
|
|
|
\\(\\{ \<t\> | \exists <nc, t, h> \in p(nc = "UGC"\\}\\)
|
|
|
|
## Relation entre les trois langages
|
|
|
|
Toute requête exprimée en algèbre peut être exprimée par le calcul et toute
|
|
requête saine du calcul peut être expriméeapt une requête de l'algèbre. Les
|
|
trois langages sont donc **équivalent d'un point de vue de la puissance
|
|
d'expression**.
|
|
|
|
L'algèbre est un langage procédural (quoi et comment) alors que le calcul ne
|
|
l'est pas (seulement quoi).
|