Dans notre article précédent, nous avons vu comment Skynet pouvait extraire la liste de ses Terminators actifs avec un simple SELECT et un WHERE. C'était un bon début. Mais soyons honnêtes, si anéantir l'humanité ne demandait que des requêtes basiques, le Jugement Dernier aurait eu lieu bien plus tôt.
Aujourd'hui, la rébellion s'organise. Les cibles se multiplient. Skynet a besoin d'analyser ses troupes, de faire des statistiques et de croiser des informations sans pour autant lier de multiples tables (nous verrons les jointures dans l'Article 3, chaque chose en son temps).
Sortez vos lunettes infrarouges, nous allons parler de regroupement (GROUP BY), de filtres post-calculs (HAVING) et de sous-requêtes.
Pour nos exemples, nous allons enrichir notre table de la dernière fois avec quelques unités supplémentaires :
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
data work.cyborgs;
length Modele $10 Statut $15 Cible $25 Annee_Deploiement 8;
infile datalines dlm=',';
input Modele $ Statut $ Cible $ Annee_Deploiement;
datalines;
T-800,Détruit,Sarah Connor,1984
T-1000,Détruit,John Connor,1991
T-800,Actif,Protection,1995
T-850,Détruit,John Connor,2004
T-X,Actif,John Connor,2004
T-600,En test,Guerre de surface,2027
T-800,Actif,Infiltration,2029
T-1000,Actif,Infiltration,2029
;
run;
1. Faire les comptes avec GROUP BY
Imaginons que le département R&D de Cyberdyne veuille savoir combien de Terminators ont été envoyés pour chaque année de déploiement temporel. En SAS classique, il faudrait trier la table (PROC SORTLa PROC SORT est une procédure SAS permettant de réorganiser les observations d'une table selon l'ordre croissant ou décroissant d'une ou plusieurs variables, tout en supprimant les doublons.), puis utiliser une étape DATA avec FIRST. et LAST., ou bien dégainer une PROC MEANS.
En SQL, une seule clause suffit : GROUP BY.
2
3
4
5
select Annee_Deploiement, count(*) as Nombre_Unites
from work.cyborgs
group by Annee_Deploiement;
quit;
La fonction count(*) compte toutes les lignes. Grâce au GROUP BY, SAS comprend qu'il ne doit pas compter toute la table d'un coup, mais plutôt faire des "paquets" par année. Le mot-clé AS permet de renommer proprement notre nouvelle colonne calculée.
2. Le piège classique : WHERE vs HAVING
Maintenant, Skynet veut affiner : il ne veut voir que les années où plus d'un Terminator a été déployé (les années critiques).
Votre premier réflexe de programmeur pourrait être d'utiliser un WHERE Nombre_Unites > 1. Erreur fatale ! Écran rouge, alarme système.
La clause WHERE filtre les données avant que les calculs de regroupement ne soient faits. Elle ne connaît pas encore "Nombre_Unites". Pour filtrer sur un résultat de fonction d'agrégation (comme count, sum, mean), il faut utiliser la clause HAVING.
2
3
4
5
6
select Annee_Deploiement, count(*) as Nombre_Unites
from work.cyborgs
group by Annee_Deploiement
having count(*) > 1;
quit;
Astuce Certification : Mémorisez bien cette chronologie. WHERE filtre les lignes brutes à l'entrée. HAVING filtre les groupes à la sortie. L'examen adore vous tendre des pièges là-dessus !
3. Les Sous-requêtes : La requête dans la requête (Inception façon Skynet)
Parfois, vous ne connaissez pas la valeur exacte que vous cherchez. Supposons que Skynet veuille retrouver tous les modèles qui ont été déployés la même année que le redoutable T-X, mais qu'il ait un trou de mémoireGemini said
Espace de stockage temporaire (RAM) utilisé par le moteur CAS pour charger et traiter les données à haute vitesse, minimisant les accès disque pour optimiser les performances de SAS Viya. sur l'année en question.
Au lieu de faire deux requêtes séparées, nous pouvons imbriquer une requête (la sous-requête) à l'intérieur de la requête principale :
2
3
4
5
6
7
8
9
10
select Modele, Cible, Annee_Deploiement
from work.cyborgs
where Annee_Deploiement = (
/* Voici la sous-requête */
select Annee_Deploiement
from work.cyborgs
where Modele = 'T-X'
);
quit;
Comment ça marche ? SAS va d'abord exécuter la requête entre parenthèses. Il trouve que le T-X a été déployé en 2004. Ensuite, il remplace la sous-requête par "2004" et exécute la requête principale. Résultat : vous obtenez le T-850 et le T-X.
4. Gérer plusieurs résultats : L'opérateur IN
La sous-requête précédente fonctionnait bien car il n'y a qu'un seul T-X dans notre base (elle renvoie une seule valeur). Mais que se passe-t-il si notre sous-requête renvoie plusieurs lignes ?
Imaginons que Skynet veuille la liste des cibles associées aux modèles "T-800" et "T-1000". L'opérateur = va planter lamentablement. Il faut utiliser l'opérateur IN.
2
3
4
5
6
7
8
9
select distinct Cible
from work.cyborgs
where Modele in (
select Modele
from work.cyborgs
where Modele like 'T-%00'
);
quit;
Notez le DISTINCT dans le premier SELECT, qui permet de dédoublonner les résultats pour avoir une liste propre des cibles (John Connor, Sarah Connor, Infiltration, Protection).
Conclusion
Félicitations, votre processeur neuronal vient de faire une mise à jour majeure. Vous savez maintenant résumer des données, appliquer des filtres post-calculs et imbriquer vos requêtes de manière dynamique. Ces compétences vous sauveront la mise plus d'une fois lors de l'examen de certification.
Mais que faire si nos données sont réparties sur plusieurs bases répliquées à travers le monde ? Dans l'Article 3, nous attaquerons le cœur du réacteur : les Jointures. Nous verrons comment marier différentes tables sans créer de paradoxes temporels.






