# Les bases de données/Les requêtes : la théorie

Dans les chapitres précédents, nous avons vu comment mémoriser des données dans une base de donnée : on utilise des tables, qui doivent respecter certaines contraintes d'intégrité. Maintenant, nous allons voir comment lire des données dans une table, et quelles opérations nous pouvons faire sur ces tables. Outre les opérations d'ajout d'une ligne, de suppression, et de modification, il existe quelques autres manipulations, que nous allons aborder dans ce chapitre. On peut classer ces opérations en deux grands groupes : un groupe d'opérations ensemblistes, inspirées de la théorie des ensembles, et un groupe d'opérations spécifiques aux bases de données relationnelles.

## Opérations ensemblistes

Les opérations ensemblistes prennent en entrée deux tables et donnent comme résultat une autre table. Elles sont au nombre de quatre :
* Union ;
* Intersection ;
* Différence ;
* Produit cartésien.
Les opérations d'union, intersection et différence ne fonctionnent que sur des tables compatibles. Par compatibles, on veut dire que ces deux tables ont exactement les mêmes attributs, les mêmes colonnes : les colonnes des deux tables ont le même nom et le même type.

### Union

L'union crée une table résultat qui contient toutes les lignes de la première et de la seconde table passées en entrée. En théorie, la table résultat ne contient pas de doublons : si une ligne est identique dans les deux tables, la table résultat ne contiendra qu'un seul exemplaire de cette ligne. Mais dans la réalité, il faut indiquer au SGBD que l'on souhaite éliminer les doublons.

### Intersection

L'intersection crée une table résultat qui contient les lignes qui sont présentes à la fois dans la première et la seconde table. En théorie, la table résultat ne contient pas de doublons : si une ligne est identique dans les deux tables, la table résultat ne contiendra qu'un seul exemplaire de cette ligne. Mais dans la réalité, il faut indiquer au SGBD que l'on souhaite éliminer les doublons.

### Différence

La différence crée une table résultat qui contient les lignes qui sont présentes dans la première table, mais pas dans la seconde. En théorie, la table résultat ne contient pas de doublons : si une ligne est identique dans les deux tables, la table résultat ne contiendra qu'un seul exemplaire de cette ligne. Mais dans la réalité, il faut indiquer au SGBD que l'on souhaite éliminer les doublons.

### Produit cartésien

Le produit cartésien crée une table résultat dans laquelle chaque ligne est une combinaison des lignes des deux autres tables. Plus précisément, chaque ligne de la première table est concaténée à une ligne de la seconde table : la table résultat contient toutes les combinaisons possibles entre une ligne de la première table et une ligne de la seconde table. Ainsi, si la première table contient N lignes, et la seconde M lignes, la table résultat contiendra N×M lignes au total.

## Opérations relationnelles

Les opérations relationnelles les plus importantes sont :
* la sélection ;
* la projection ;
* la jointure.

### Projection

La projection est une opération qui consiste à ne garder que certaines colonnes dans une table :
* elle prend une table en opérande, ainsi qu'un ou plusieurs noms de colonnes ;
* ensuite, elle sélectionne les colonnes de la table qui lui sont indiquées ;
* elle copie ces colonnes dans une nouvelle table.
Pour les exemples qui vont suivre, nous allons reprendre la table vue plus haut.
| Nom | Age | Taille |
| Johnson | 25 | 172 |
| Harry | 54 | 180 |
| Sally | 70 | 164 |
| George | 29 | 170 |
| Helena | 14 | 154 |
| Peter | 8 | 180 |
Dans cette table, on peut demander de sélectionner uniquement la colonne "Nom", avec une projection.
* Nom
* Johnson
* Harry
* Sally
* George
* Helena
* Peter
On peut aussi demander à sélectionner plusieurs colonnes, par exemple les colonnes "Age" et "Taille".
| Age | Taille |
| 25 | 172 |
| 54 | 180 |
| 70 | 164 |
| 29 | 170 |
| 14 | 154 |
| 8 | 180 |

### Sélection

La sélection est une opération qui sélectionne les lignes d'une table qui respectent une condition bien précise :
* elle prend une table en opérande, ainsi qu'une condition ;
* ensuite, elle sélectionne les lignes de la table qui respectent la condition ;
* elle copie ces lignes dans une nouvelle table.

#### Conditions simples

La condition en question est souvent une sous-opération qui permet de comparer le contenu d'un attribut avec une autre information : une constante, le contenu d'un autre attribut, etc. Les comparaisons disponibles sont les comparaisons de :
* supériorité ;
* infériorité ;
* supériorité stricte (n'accepte pas l'égalité) ;
* infériorité stricte (n'accepte pas l'égalité) ;
* égalité ;
* différence.
D'autres tests sont possibles sur les SGBD actuels, mais nous laisserons cela pour plus tard.
Prenons un exemple, avec une table qui contient une liste de personnes. La table Personne mémorise, pour chaque ligne de la table : le nom de la personne, son âge, sa taille.
| Nom | Age | Taille |
| Johnson | 25 | 172 |
| Harry | 54 | 180 |
| Sally | 70 | 164 |
| George | 29 | 170 |
| Helena | 14 | 154 |
| Peter | 8 | 180 |
Dans cette table, on peut sélectionner toutes les personnes dont l'âge est inférieur à 18 ans (les personnes mineures). Il suffit pour cela d'indiquer à l'opération de sélection que l'on souhaite récupérer les lignes dont l'attribut âge est inférieur à 18 : age < 18. En faisant cela, on obtient une nouvelle table qui ne contiendra que les lignes pour lesquelles la condition est vérifiée. Avec la table vue plus haut, cette sélection donnerait la table suivante :
| Nom | Age | Taille |
| Helena | 14 | 154 |
| Peter | 8 | 180 |
Comme autre exemple, on peut sélectionner les personnes dont la taille est supérieure à 170. Dans ce cas, la comparaison vérifie, pour chaque ligne, si l'attribut Taille de la ligne est supérieur à 170 : Taille > 170. Avec la table vue plus haut, cette sélection donnerait la table suivante :
| Nom | Age | Taille |
| Johnson | 25 | 172 |
| Harry | 54 | 180 |
| George | 29 | 170 |
| Peter | 8 | 180 |
Enfin, dernier exemple : on peut sélectionner les lignes de la table où le nom n'est pas "Johnson". Pour cela, il suffit de vérifier si l'attribut de la ligne n'est pas "Johnson" : Nom != Johnson. Avec la table vue plus haut, cette sélection donnerait la table suivante :
| Nom | Age | Taille |
| Harry | 54 | 180 |
| Sally | 70 | 164 |
| George | 29 | 170 |
| Helena | 14 | 154 |
| Peter | 8 | 180 |

#### Conditions composées

Il est possible de ne sélectionner que les lignes qui respectent plusieurs conditions en même temps. Pour cela, on peut combiner plusieurs conditions en une seule, avec des opérateurs respectivement appelées ET et OU logiques.

### Jointure

Les jointures (car ils en existe plusieurs types) sont des opérations assez difficiles à décrire. Dans le détail, la jointure prend en entrée deux tables et fournit une table résultat. Chaque ligne de la table résultat est le résultat de la concaténation d'une ligne de la première table et d'une ligne de la seconde. Cependant, cette concaténation n'est effectuée que si les deux lignes ont un ou plusieurs attributs en commun : on peut demander à ne garder que les lignes pour lesquelles l'attribut nommé "…" a la même valeur dans les deux tables. De plus, la colonne présente dans les deux tables n'est présente qu'en un seul exemplaire dans la table résultat. Pour simplifier, on peut dire qu'il s'agit d'une combinaison entre le produit cartésien de deux tables, d'une sélection et d'une projection. Le produit cartésien concatène les lignes des deux tables, la sélection ne conserve que les lignes pour lesquelles les attributs sont identiques, et la projection supprime la colonne en double.