SQL : requêtes de regroupement
Dossier "SAM l'Informaticien" de novembre 2001 par Daniel Lucazeau

i SQL est un langage de requêtes, d'interrogation de tables relationnelles ce n'est pas uniquement pour restituer l'information ligne à ligne. Nous allons étudier les requêtes de regroupement qui permettent de faire une analyse statistique de la base de données par exemple.

Regrouper les données pourquoi et comment faire ?

L'objectif de ce traitement des données est, comme le nom l'indique, de "regrouper" les données, chaque groupe étant l'ensemble des lignes ayant une valeur commune. Nous devons donc indiquer à SQL comment il doit fabriquer les paquets et ce que l'on veut faire comme opération. C'est la clause GROUP BY de la phrase SQL qui nous permet de donner le regroupement à réaliser :
SELECT ... FROM ... GROUP BY ...

Nous pouvons ensuite étudier les caractéristiques de ces groupes : en calculer l'effectif par exemple. Par exemple, à partir d'une base de suivi de visites d'un site on peut regrouper les données par serveur d'origine, par moteur de recherche, par date de visite.

La preuve par les exemples

Prenons une table d'individus dont nous connaissons les dates de naissance, il peut être intéressant de connaître le nombre de personnes par année de naissance :
SELECT date, count(date) FROM table GROUP BY anneeDeNaissance

Cette requête avec MySql ou Access devient :
SELECT year( dateDeNaissance), count(*) AS cpt FROM organo GROUP BY year( dateDeNaissance)

Nous pouvons réécrire la requête comme ceci :
SELECT year( dateDeNaissance) AS adn, count(*) FROM organo GROUP BY adn

La fonction Year renvoie l'année d'un champ 'date'. Voilà un extrait du résultat :
+-----------+
| adn  |cpt |
+-----------+
| 1959 | 29 |
| 1960 | 17 |
| 1961 | 18 |
| 1962 | 18 |
| 1963 | 19 |
| 1964 | 12 |

Le résultat nous est donné trié par année, nous pouvons l'obtenir trié sur le nombre :
SELECT year( dateDeNaissance), count(*) AS cpt FROM organo GROUP BY year( dateDeNaissance) ORDER BY cpt

Pour Access il faut ORDER BY count(*) !!!

Sélectionner les groupes

SQL autorise de ne manipuler que les groupes vérifiant certaines conditions ; nous pourrions ne nous intéressés qu'aux individus dont le code postal est en 44, j'ai pris ce département car il est dans ma base de tests ;-)

Il faut alors utiliser HAVING qui est à GROUP BY ce que WHERE est à SELECT ! Ce qui donne pour MySql :
SELECT year( dateDeNaissance) AS adn, count(idElement) AS cpt, CP FROM organo GROUP BY dateDeNaissance HAVING SUBSTRING( CP, 1, 2) = '44'

Le standard SQL spécifie que les champs utilisés par HAVING doivent être référencés au moins dans GROUP BY, pour MySql, ils doivent l'être mais que dans SELECT ! La fonction SUBSTRING devient MID dans ACCESS.

WHERE ou HAVING ?

Il est possible de sélectionner les lignes à traiter avec la clause WHERE standard. Seules les lignes sélectionnées par WHERE entreront dans la constitution des groupes. L'ordre des clauses est:
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ...

Par exemple, nous pourrions très bien n'étudier que les groupes d'année de naissance pour les femmes :
SELECT year( dateDeNaissance) AS adn, count(idElement) AS cpt FROM organo WHERE sexe = 'F' GROUP BY dateDeNaissance

On se rend alors compte que la clause HAVING ci-dessus peut-être remplacé par une clause WHERE, et de façon plus pertinente puisque nous éliminons des lignes avant de les regrouper.

La clause HAVING est intéressante quand elle porte directement sur une valeur issue du regroupement. Intéressons-nous par exemple aux groupes dont les effectifs sont supérieurs à 10 :
SELECT year( dateDeNaissance) AS adn, count(idElement) AS cpt FROM organo GROUP BY adn HAVING cpt >10 ORDER BY cpt

Conclusion

Nous avons survolé les requêtes de regroupement, nous y reviendrons car elles offrent des possibilités d'analyse des données très intéressantes.

Le fichier exemple est disponible par messagerie ici. Il est au format .txt avec des ';' comme séparateur de champs

A bientôt ...

Daniel Lucazeau
www.ajornet.com
Chef de projet Internet

 

Tous droits réservés - Reproduction même partielle interdite sans autorisation préalable