Les expressions de table communes, ou CTE en abrégé, sont simplement une technique pour créer un ensemble temporaire d'enregistrements qui peuvent être référencés dans une instruction INSERT, SELECT, UPDATE ou DELETE.
Les expressions de table communes ont été introduites par Microsoft dans SQL Server 2005. Elles ne sont pas stockées en tant qu'objets dans la mémoire de la base de données car leur durée de vie est égale au temps d'exécution de la requête. Dès qu'une requête est terminée, elles sont supprimées de la mémoire de la base de données. Les CTE peuvent être référencés dans une requête autant de fois que vous le souhaitez et ils peuvent également se référencer eux-mêmes.
Créons une base de données avec une table d'étudiants et insérons-y des enregistrements d'étudiants fictifs. Nous utiliserons cette base de données pour écrire des requêtes CTE. Comme toujours, assurez-vous d'être bien sauvegardé avant d'expérimenter un nouveau code. Consultez cet article sur la sauvegarde SQL si vous n'êtes pas sûr.
Exécutez les requêtes suivantes sur votre serveur.
CREATE DATABASE schooldb CREATE TABLE student ( id INT PRIMARY KEY, name VARCHAR(50) NOT NULL, gender VARCHAR(50) NOT NULL, DOB datetime NOT NULL, total_score INT NOT NULL, ) INSERT INTO student VALUES (1, 'Jolly', 'Female', '12-JUN-1989', 500), (2, 'Jon', 'Male', '02-FEB-1974', 545), (3, 'Sara', 'Female', '07-MAR-1988', 600), (4, 'Laura', 'Female', '22-DEC-1981', 400), (5, 'Alan', 'Male', '29-JUL-1993', 500), (6, 'Kate', 'Female', '03-JAN-1985', 500), (7, 'Joseph', 'Male', '09-APR-1982', 643), (8, 'Mice', 'Male', '16-AUG-1974', 543), (9, 'Wise', 'Male', '11-NOV-1987', 499), (10, 'Elis', 'Female', '28-OCT-1990', 400);
Créons maintenant une expression de table commune très simple. Ce CTE contiendra les enregistrements de tous les étudiants nés avant le 1er janvier 1985. Jetez un œil au script suivant.
USE schooldb; WITH OldStudents AS ( SELECT * FROM student WHERE DOB < '1985-01-01' )
Pour créer un CTE, vous devez commencer par le mot-clé "AVEC" suivi du nom du CTE et du mot-clé "AS".
Ensuite, entre parenthèses, vous devez écrire la requête qui renvoie les enregistrements que le CTE stockera temporairement. Dans le script ci-dessus, nous avons créé un CTE nommé "OldStudents".
Cependant, notez que si vous essayez d'exécuter la requête ci-dessus, vous obtiendrez une erreur. En effet, une fois que vous avez créé un CTE, vous devez l'utiliser immédiatement.
Sélectionnons tous les enregistrements de notre CTE "OldStudents" nouvellement créé. Essayez le script suivant sur votre serveur.
USE schooldb; WITH OldStudents AS ( SELECT * FROM student WHERE DOB < '1985-01-01' ) SELECT * FROM OldStudents
Le script ci-dessus récupérera l'ensemble d'enregistrements suivant :
Calcul de l'agrégat via CTE
Comme les tables, vous pouvez effectuer des fonctions d'agrégation sur CTE. Examinons un autre exemple de CTE.
USE schooldb; WITH SumofScores AS ( SELECT gender, SUM(total_score) as SumScore FROM student GROUP BY gender ) SELECT AVG (SumScore) FROM SumofScores
Dans l'exemple ci-dessus, nous avons créé un CTE nommé SumofScores. Ce CTE contient la somme des valeurs stockées dans la colonne total_score de la table des étudiants. Le résultat est regroupé par la colonne sexe. Les données stockées par le CTE ressemblent à ceci dans la mémoire :
Ensuite, nous avons exécuté la fonction AVG sur la colonne "SumScore" du CTE. Le résultat final du script sera la moyenne de 2400 et 2730 soit 2565.
C'est un peu plus compliqué que l'exemple précédent mais démontre plus clairement le concept de CTE.
Étiquetage des colonnes dans CTE
Dans l'exemple précédent, nous avons ajouté un alias à la deuxième colonne du CTE. Nous l'avons renommé "SumScore". C'est une façon d'étiqueter les colonnes dans CTE et est similaire aux alias de colonne de table.
Cependant, il existe une autre façon de définir les noms de colonne dans CTE. Examinez la requête suivante.
USE schooldb; WITH SumofScores(Gender, SumScore) AS ( SELECT gender, SUM(total_score) FROM student GROUP BY gender ) SELECT AVG (SumScore) From SumofScores
Dans ce script, nous avons ajouté les noms de colonne du CTE "SumofScores" entre parenthèses après le nom du CTE. Chaque nom de colonne est séparé par une virgule.
Si vous regardez l'instruction SELECT après le CTE, vous pouvez voir que nous faisons alors référence à la colonne "SumScore" que nous avons créée entre parenthèses après le nom du CTE.
Créer plusieurs CTE
Jusqu'à présent, tous les exemples n'ont utilisé qu'une seule expression de table commune pour plus de clarté. Vous pouvez créer une liste de CTE en même temps, puis les utiliser toutes en combinaison dans l'ensemble de résultats final.
Ceci est mieux expliqué à l'aide d'un exemple. Jetez un œil au script suivant ci-dessous.
Ici, nous allons créer deux CTE. Le premier CTE contiendra tous les dossiers des étudiants nés avant le 1er janvier 1985. Le second CTE contiendra tous les dossiers des étudiants nés le 1er janvier 1985 ou après.
Après cela, nous utiliserons des instructions de sélection pour récupérer tous les enregistrements des deux CTE. Les enregistrements récupérés seront fusionnés à l'aide de l'instruction UNION. Enfin, l'enregistrement fusionné sera trié par ordre croissant de date de naissance.
USE schooldb; WITH OldStudents AS ( SELECT * FROM student WHERE DOB < '1985-01-01' ), YoungStudents AS ( SELECT * FROM student WHERE DOB >= '1985-01-01' ) (SELECT * FROM OldStudents UNION SELECT * FROM YoungStudents) ORDER BY DOB
Dans la requête SQL ci-dessus, nous avons créé deux CTE :"OldStudents" et "YoungStudents". Il convient de mentionner que vous n'avez pas besoin d'utiliser le mot-clé "AVEC" avec chaque CTE. Vous n'êtes tenu de l'utiliser qu'avant le premier CTE du script, après quoi vous pouvez créer n'importe quel nombre de CTE en les séparant par une virgule.
Le script ci-dessus récupère les résultats suivants :