Requêtes agrégats

Nous considérons maintenant des traitements d'agrégation (e.g. calcul de moyenne) qui ne sont pas couverts par l'algèbre relationnelle classique et le calcul relationnel. Nous expliquons ici le principe sur SQL, et étendons l'algèbre pour représenter ces concepts. Nous ne considérons donc plus ici le calcul relationnel.

Les fonctions d'agrégation, les clauses GROUP BY et HAVING permettent de « résumer » un ensemble de n-uplets. La clause GROUP BY précise les attributs de groupement. Les fonctions d'agrégation sont ensuite appliquées sur chaque groupe. Enfin, la clause HAVING permet de spécifier des conditions sur les groupes. Il s'agit donc ici d'une condition globale à un groupe. Ces conditions peuvent être la valeur min, max, moyenne, ou la somme d'un attribut \(a\) sur un groupe (MIN(a), MAX(a), AVG(a), SUM(a)), le nombre de lignes d'un groupe (COUNT(*)), ou le nombre de lignes d'un groupe ayant une valeur distincte d'un attribut \(a\) particulier (COUNT(distinct a)).

Nous introduisons l'opérateur \(_{a_1,\ldots a_n}\gamma_{F_1(a_{n+1}, \ldots a_p), \ldots F_k(a_{n+1}, \ldots a_p)}\) pour l'algèbre relationnelle. Cet opérateur regroupe ensemble tous les n-uplets qui ont la même valeur sur les attributs \(a_1,\ldots a_n\) puis calcule pour chacun de ces groupes la valeur des fonctions \(F_1(a_{n+1}, \ldots a_p), \ldots F_k(a_{n+1}, \ldots a_p)\). Notons qu'implicitement une projection est effectuée sur les attributs \(a_1,\ldots a_n\), auxquels on rajoute les valeurs des fonctions. Si on ne met aucun ensemble d'attributs, alors tous les n-uplets de la table sont regroupés ensembles. On peut également ne calculer aucune valeur de fonction. Dans ce cas, le GROUP BY revient à faire un DISTINCT dans le SELECT.

ExempleAnnée de production moyenne des films

1
SELECT AVG(annee)FROM film;

Algèbre :

\(\gamma_{AVG(annee)}(FILM)\)

ExempleNombre total de films dans lequel chaque acteur a joué.

Il s'agit ici de regrouper tous les n-uplets concernant le même acteur, puis pour chaque groupe appliquer l'opérateur d'agrégation COUNT(DISTINCT idfilm) qui donnera le nombre de films différents dans lesquels il a joué.

1
SELECT idacteur AS id, COUNT(DISTINCT idfilm)AS Nb_films
2
FROM film f NATURAL JOIN jouedans jd
3
GROUP BY idacteur

Algèbre :

\(\pi_{idacteur, COUNT(DISTINCT\ idfilm)}(_{idacteur}\gamma_{COUNT(DISTINCT\ idfilm)}(FILM \bowtie JOUEDANS))\)

ExempleAnnée de production la plus ancienne pour chaque acteur ayant joué dans au moins 3 films de Hitchcock.

1
SELECT idacteur, MIN(annee)AS annee_debut
2
FROM film f NATURAL JOIN jouedans jd
3
WHERE f.directeur='Hitchcock' 
4
GROUP BY idacteur
5
HAVING COUNT(*)> 2;

Algèbre :

\(\pi_{annee\_debut, idacteur}(\sigma_{COUNT(*) > 2}(\rho_{MIN(annee)\rightarrow annee\_debut)}(_{idacteur}\gamma_{MIN(annee), COUNT(*)} (\sigma_{directeur="Hitchcock"}FILM \bowtie JOUEDANS))))\)