Documentation PostgreSQL 7.4.29 | ||||
---|---|---|---|---|
Précédent | Arrière rapide | Chapitre 2. Le langage SQL | Avance rapide | Suivant |
Comme la plupart des autres produits de bases de données
relationnelles, PostgreSQL supporte les
fonctions d'agrégat. Une fonction d'agrégat calcule un seul
résultat à partir de plusieurs lignes en entrée. Par exemple, il
y a des agrégats pour calculer le compte
(count
), la somme (sum
),
la moyenne (avg
), le maximum
(max
) et le minimum
(min
) d'un ensemble de lignes.
Comme exemple, nous pouvons trouvez la température la plus haute parmi les températures les plus faibles avec :
SELECT max(temp_basse) FROM temps;
max ----- 46 (1 row)
Si nous voulons connaître dans quelle ville (ou villes) ces lectures se sont produites, nous pouvons essayer
SELECT ville FROM temps WHERE temp_basse = max(temp_basse); FAUX
mais cela ne marchera pas puisque l'agrégat
max
ne peut pas être utilisé dans une clause
WHERE. (Cette restriction existe parce que la
clause WHERE détermine les lignes qui seront
traitées par l'agrégat ; donc les lignes doivent être évaluées
avant que les fonctions d'agrégat calculent.)
Cependant, comme cela est souvent le cas, la requête peut être
répétée pour arriver au résultat attendu, ici en utilisant une
sous-requête :
SELECT ville FROM temps WHERE temp_basse = (SELECT max(temp_basse) FROM temps);
ville --------------- San Francisco (1 row)
Ceci est bon car la sous-requête est un calcul indépendant qui traite son propre agrégat séparément à partir de ce qui se passe dans la requête externe.
Les agrégats sont également très utiles s'ils sont combinés avec les clauses GROUP BY. Par exemple, nous pouvons obtenir la plus haute température parmi les températures les plus faibles observées dans chaque ville avec
SELECT ville, max(temp_basse) FROM temps GROUP BY ville;
ville | max ---------------+----- Hayward | 37 San Francisco | 46 (2 rows)
ce qui nous donne une ligne par ville dans le résultat. Chaque résultat d'agrégat est calculé avec les lignes de la tables correspondant à la ville. Nous pouvons filtrer ces lignes groupées en utilisant HAVING :
SELECT ville, max(temp_basse) FROM temps GROUP BY ville HAVING max(temp_basse) < 40;
ville | max ---------+----- Hayward | 37 (1 row)
ce qui nous donnes le même résultat uniquement pour les villes qui ont toutes leurs valeurs de temp_basse en-dessous de 40. Pour finir, si nous nous préoccupons seulement des villes dont le nom commence par << S >>, nous pouvons faire
SELECT ville, max(temp_basse) FROM temps WHERE ville LIKE 'S%'(1) GROUP BY ville HAVING max(temp_basse) < 40;
Il est important de comprendre l'interaction entre les agrégats et les clauses SQL WHERE et HAVING. La différence fondamentale entre WHERE et HAVING est que WHERE sélectionne les lignes en entrée avant que les groupes et les agrégats ne soient traités (donc, cette clause contrôle quelles lignes vont dans le calcul de l'agrégat) tandis que HAVING sélectionne les lignes groupées après que les groupes et les agrégats aient été traités. Donc, la clause WHERE ne doit pas contenir des fonctions d'agrégat ; cela n'a aucun sens d'essayer d'utiliser un agrégat pour déterminer quelles lignes seront en entrée des agrégats. D'un autre côté, la clause HAVING contient toujours des fonctions d'agrégat. (Pour être précis, vous êtes autorisés à écrire une clause HAVING qui n'utilise pas d'agrégats, mais c'est inutile : la même condition pourra être utilisée plus efficacement par un WHERE.)
Remarquez que nous pouvons appliquer la restriction sur le nom de la ville dans WHERE puisque cela n'a besoin d'aucun agrégat. C'est plus efficace que d'ajouter la restriction dans HAVING parce que nous évitons le groupement et les calculs d'agrégats pour toutes les lignes qui ont échoué lors du contrôle fait par WHERE.
Précédent | Sommaire | Suivant |
Jointures entre les tables | Niveau supérieur | Mises à jour |