--- 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. ![Schema représentan l'Union](./images/union.svg) ### Intersection \\( A \cap B \\) est une relation qui inclue les *n_uplets* appartenant à A et à B et seulement ceux-ci. ![Schema représentant l'Intersection](./images/intersection.svg) ### Différence \\( A - B \\) est une relation qui inclue tous les *n_uplets* appartenant à A mais pas à B. ![Schema représentant la différence](./images/difference.svg) 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. ![Notre schéma de base de donnée compagnie aérienne](../2-introduction_modele_relationnel/images/schema_bdd.svg) 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 \\(\\{ \ | \exists \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).