Retour à la liste des articles Articles
19 minutes de lecture

6 exemples utiles d'ETC dans SQL Server

Comment pouvez-vous utiliser les CTE dans SQL Server dans votre vie professionnelle de tous les jours en tant que professionnel des données ? Nous allons répondre à cette question en vous donnant six exemples.

CTE est l'abréviation de Common Table Expression. Il s'agit d'une fonctionnalité relativement nouvelle de SQL Server qui a été mise à disposition avec SQL Server 2005.

Un CTE est un résultat temporaire nommé. Ce résultat n'est disponible que pour la requête qui l'exécute. Il n'est pas stocké et n'occupe donc pas d'espace disque. Un CTE est quelque peu similaire à une table temporaire et peut être utilisé comme n'importe quelle autre table. Les CTE sont le plus souvent utilisés avec une déclaration SELECT, mais ils peuvent également être utilisés avec INSERT, UPDATE et DELETE.

Les CTE sont l'un des concepts les plus complexes de SQL Server. Pour profiter de leurs avantages, votre approche de l'apprentissage doit être soigneusement structurée et non précipitée. Notre cours Requêtes récursives in MS SQL Server vous montrera comment écrire un CTE simple dans SQL Server pour commencer. Vous apprendrez ensuite à écrire plusieurs CTE, à les imbriquer et à les utiliser dans les instructions SELECT, INSERT, UPDATE et DELETE. Enfin, vous apprendrez à connaître les structures de données hiérarchiques et graphiques et à utiliser les CTE récursifs dans SQL Server pour interroger ces données. Pour vous permettre de vous entraîner, le cours comporte 112 exercices interactifs à réaliser.

Il existe, bien sûr, d'autres façons d'apprendre les CTE que vous pouvez également consulter.

Syntaxe des CTE dans SQL Server

En règle générale, la syntaxe des CTE dans SQL Server ressemble à l'exemple suivant :

WITH cte AS (  
  SELECT
    ...
)

SELECT
  ...
FROM cte;

Les CTE doivent toujours commencer par le mot-clé WITH. Viennent ensuite le nom de l'ETC, le mot-clé AS et les parenthèses. Vous définissez l'ETC entre ces parenthèses. La définition, comme vous le verrez dans nos exemples, implique l'écriture de l'instruction SELECT. Vous trouverez plus de détails dans cet article qui explique ce qu'est un ETC.

6 exemples d'ETC dans SQL Server

1 : Trouver les nombres moyens les plus élevés et les plus bas des flux quotidiens

Dans les cinq premiers exemples, nous utiliserons le même ensemble de données. Il s'agit de données inventées provenant d'une plateforme de streaming musical imaginaire, que nous appellerons Terpsichore.

L'ensemble de données se compose de trois tableaux. La première est artistet voici la requête de création de table. Cette table contient les colonnes suivantes :

  • id - L'ID de l'artiste et la clé primaire de la table.
  • artist_name - Le nom de l'artiste.
idartist_name
1Prince
2Jimi Hendrix
3Santana

Ce tableau présente trois artistes.

La table suivante est albums. Voici la requête pour la créer. Et voici les colonnes qu'elle contient :

  • id - L'ID de l'album et la clé primaire de la table.
  • artist_id - L'artiste (et la clé étrangère de la table).
  • album_title - Le titre de l'album.
  • year_released - L'année de sortie de l'album.
idartist_idalbum_titleyear_released
12Are You Experienced1967
22Axis: Bold as Love1967
31Dirty Mind1980
42Electric Ladyland1968
53Abraxas1970
6119991982
73Santana III1971
83Santana1969
91Prince1979
101Controversy1981

La table contient dix albums.

La dernière table est streams. Il présente les données de diffusion en continu pour les chansons individuelles. Vous pouvez créer le tableau à l'aide de cette requête. Et les colonnes :

  • id - L'ID du flux et la clé primaire de la table.
  • artist_id - L'ID de l'artiste et une clé étrangère.
  • album_id - L'ID de l'album et une clé étrangère.
  • song_title - Le nom de la chanson.
  • date - La date du stream.
  • number_of_streams - Le nombre de fois que la chanson a été jouée à une date donnée.
  • pay_per_stream - Valeur (en dollars) que Terpsichore verse aux artistes pour chaque diffusion.
idartist_idalbum_idsong_titledatenumber_of_streamspay_per_stream
119I Wanna Be Your Lover2023-01-015970.013
216Little Red Corvette2023-01-014970.013
316D.M.S.R.2023-01-012170.013
413Uptown2023-01-0197480.013
513Do It All Night2023-01-012080.013

Ce tableau comporte 45 lignes. Nous ne vous montrerons que les cinq premières, afin que vous puissiez vous faire une idée de la logique du tableau.

Et maintenant, l'exemple ! Commençons par écrire un seul CTE dans SQL Server. Nous allons le faire pour calculer le nombre moyen le plus élevé et le plus bas de flux quotidiens.

Voici le code ; nous l'expliquerons plus loin :

WITH daily_streaming AS (
  SELECT date,
	   MIN(number_of_streams) AS minimum_streaming,
	   MAX(number_of_streams) AS maximum_streaming
  FROM streams
  GROUP BY date
)

SELECT AVG(minimum_streaming) AS average_minimum_daily_streaming,
	 AVG(maximum_streaming) AS average_maximum__daily_streaming
FROM daily_streaming;

Un CTE est idéal pour décomposer la logique de n'importe quel calcul dans SQL Server.

N'oubliez pas que plusieurs chansons sont diffusées en continu au cours d'une même journée. L'objectif de notre CTE est d'obtenir le nombre le plus bas et le plus élevé de streams chaque jour.

Comme indiqué précédemment, un CTE dans SQL Server commence toujours par le mot-clé WITH, suivi du nom du CTE. Notre CTE s'appelle daily_streaming.

Le mot-clé AS est suivi d'une déclaration SELECT entre parenthèses, c'est-à-dire la définition de l'ETC. Nous l'utilisons, ainsi que les fonctions d'agrégation MIN() et MAX(), pour calculer le nombre le plus élevé et le plus bas de flux par date.

L'instruction SELECT suivante utilise les données de l'ETC, en y faisant référence dans la clause FROM. Comme nous l'avons dit, un CTE peut être utilisé comme n'importe quelle autre table. Dans cette déclaration SELECT, nous utilisons la fonction d'agrégation AVG() pour obtenir la moyenne des pics et des creux des flux quotidiens.

Le résultat montre que le point le plus bas moyen est de 90 flux. La moyenne des flux quotidiens les plus élevés est de 8 367.

average_minimum_daily_streamingaverage_maximum__daily_streaming
908,367

2 : Calculer le montant total moyen des droits payés par chanson

Mettons maintenant en pratique ce que nous avons appris. Nous allons à nouveau écrire un seul ETC.

Le problème à résoudre est de trouver le montant total moyen payé par Terpsichore pour chaque chanson.

Voici la solution :

WITH paid_per_song AS (
  SELECT song_title,
	   SUM(number_of_streams * pay_per_stream) AS total_pay
  FROM streams
  GROUP BY id, song_title, pay_per_stream
)

SELECT song_title,
       AVG(total_pay) AS average_total_pay
FROM paid_per_song
GROUP BY song_title
ORDER BY average_total_pay DESC;

Nous utilisons le CTE du serveur SQL pour calculer le montant total payé par chanson en multipliant le nombre de streams par le montant payé par stream, puis en l'additionnant à l'aide de la fonction d'agrégation SUM().

Il n'y a pas de changement dans la syntaxe du CTE : d'abord WITH, puis le nom du CTE, et ensuite AS.

Nous utilisons ensuite un SELECT qui invoque l'ETC pour calculer la rémunération moyenne par chanson. C'est simple : utilisez AVG(), faites référence à l'ETC dans FROM et groupez par titre de chanson.

La requête renvoie le résultat suivant :

song_titleaverage_total_pay
Uptown47.4803330
I Wanna Be Your Lover36.8203330
Little Red Corvette33.8693330
The Wind Cries Mary23.6138660
Do It All Night12.4063330
If 6 Was 97.7824000
Samba Pa Ti7.5735000
All Along the Watchtower5.2032000
Bold as Love4.7424000
Burning of the Midnight Lamp3.7333330
D.M.S.R.3.1633330
Taboo2.4871000
Jingo2.1604000
Everything's Coming Our Way1.5466000
Incident at Neshabur0.9207000

Nous constatons que la chanson "Uptown" a rapporté 47,4803330 $ au total. Les deuxième et troisième chansons en termes de revenus sont "I Wanna Be Your Lover" et "Little Red Corvette". Si vous êtes un fan de cet artiste, vous n'avez pas besoin de SQL pour savoir qui a écrit ces trois chansons.

3 : Trouver l'album le plus diffusé de chaque artiste

Dans cet exercice, vous devez trouver l'album le plus diffusé de chaque artiste. Produisez le nom de l'artiste, le titre de l'album et le nombre de streams par album.

Il s'agit là encore d'une requête ne comportant qu'un seul CTE. Cependant, elle est un peu plus complexe que les deux précédentes - il y a quelques JOIN et une fonction de fenêtre.

WITH album_streaming AS (
  SELECT artist_id,
	   album_id,
	   SUM(number_of_streams) AS streams_by_album,
	   RANK() OVER (PARTITION BY artist_id ORDER BY SUM(number_of_streams) DESC) AS streaming_rank
  FROM streams
  GROUP BY artist_id, album_id
)

SELECT artist_name,
       album_title,
	 streams_by_album
FROM album_streaming alst
JOIN albums al
ON alst.album_id = al.id
JOIN artist ar 
ON al.artist_id = ar.id
WHERE streaming_rank = 1;

Là encore, la syntaxe CTE de SQL Server est familière. Concentrons-nous donc sur ce que fait cet ETC. Nous l'utilisons pour classer les albums par artiste. Tout d'abord, nous sélectionnons les ID de l'artiste et de l'album. Ensuite, nous utilisons SUM() pour calculer le nombre de flux par album.

Vient ensuite la partie cruciale : le classement des résultats à l'aide de la fonction de fenêtre RANK(). Une fois la fonction invoquée, nous voyons la clause OVER() - une clause obligatoire pour les fonctions SQL window. Nous partitionnons l'ensemble de données en fonction de l'identifiant de l'artiste et nous classons les données dans chaque partition en fonction du nombre de flux, par ordre décroissant.

Qu'est-ce que cela signifie en pratique ? Cela signifie que la fonction window classera les albums d'un artiste, puis le classement sera repris lorsque la fonction atteindra l'artiste suivant, et ainsi de suite. L'album de l'artiste ayant reçu le plus grand nombre de streams sera classé en premier dans sa partition.

Si vous n'exécutez que l'instruction SELECT dans l'ETC, vous obtiendrez le résultat suivant :

artist_idalbum_idstreams_by_albumstreaming_rank
1313,8201
168,5462
198,4973
257,7221
273,6672
281,9643
3111,0691
325,8712
344,1893

Comme vous pouvez le voir, les albums du premier artiste sont classés du premier au troisième, en fonction du nombre de streams. Lorsque nous atteignons le deuxième artiste, le classement recommence. Il en va de même pour le troisième artiste.

Voyons maintenant ce que fait la deuxième instruction SELECT. En fait, ce n'est pas très compliqué. Elle renvoie le nom de l'artiste et de l'album ainsi que le nombre de streams. Ce qui complique cette requête, c'est que nous devons joindre trois tables.

La première jointure est l'ETC album_streaming. Ensuite, nous la joignons avec albums puis avec la table artist . Enfin, nous filtrons les données à l'aide de la clause WHERE, car nous ne nous intéressons qu'à l'album le plus diffusé.

Vous obtiendrez ce résultat :

artist_namealbum_titlestreams_by_album
PrinceDirty Mind13,820
Jimi HendrixAre You Experienced11,069
SantanaAbraxas7,722

L'album de Prince le plus diffusé est "Dirty Mind", avec 13 820 diffusions. Pour Jimi Hendrix, l'album le plus diffusé est "Are You Experienced", et pour Santana, c'est "Abraxas".

Cette solution utilise les fonctions de fenêtre, voici donc un rappel de leur fonctionnement pour le classement des données.

4 : Calculer le nombre moyen de streams par chanson et le comparer au nombre moyen de streams par date

Les choses se compliquent maintenant. Mais pas trop, ne vous inquiétez pas. Nous nous appuyons sur ce que nous avons appris jusqu'à présent sur les CTE dans le serveur SQL.

Ici, nous devons trouver le nombre moyen de flux par chanson. Nous devons ensuite calculer le nombre moyen de flux par date.

La sortie doit indiquer les deux mesures. Elle doit également indiquer la différence entre le nombre moyen de streams par chanson et la moyenne quotidienne (en pourcentage), le titre de la chanson et les dates.

Jusqu'à présent, nous avons écrit des requêtes avec un CTE. Cette fois, la solution consiste en deux CTE. Voyons comment cela fonctionne :

WITH streams_per_song AS (
  SELECT song_title,
	   AVG(number_of_streams) AS average_streams_per_song
  FROM streams
  GROUP BY song_title
),

streams_per_date AS (
  SELECT date,
	   AVG(number_of_streams) AS average_streams_per_date
  FROM streams
  GROUP BY date
)

SELECT song_title,
	 average_streams_per_song,
	 date,
	 average_streams_per_date,
	 (average_streams_per_song - average_streams_per_date)/CAST(average_streams_per_date AS DECIMAL(10,2))*100 AS diff_from_daily_average
FROM streams_per_song, streams_per_date;

Le premier ETC est écrit comme d'habitude. Nous l'utilisons pour calculer le nombre moyen de streams par chanson avec AVG().

Après avoir fermé les parenthèses, la première ETC doit être séparée de la seconde par une virgule.

Ensuite, nous écrivons la deuxième ETC. Et voilà ! Il n'y a pas de WITH! C'est exact. Lorsque vous écrivez plusieurs CTE dans une requête dans SQL Server, vous écrivez WITH uniquement devant le premier CTE. Le deuxième (et tout autre CTE suivant) commence par le nom du CTE ; tout le reste est identique.

Cette deuxième requête permet de calculer le nombre moyen de flux par date. Là encore, nous utilisons la fonction AVG().

Le troisième site SELECT utilise les données des deux CTE. Elle renvoie toutes les colonnes requises. La dernière colonne est diff_from_daily_average. Nous la calculons en soustrayant le nombre moyen de streams par date du nombre moyen de streams par chanson. La différence est divisée par la moyenne des flux par date et multipliée par 100 pour obtenir le pourcentage. Nous avons également converti le résultat en un type de données décimal à l'aide de la fonction CAST().

En raison de la taille de la sortie, nous n'afficherons que les premières lignes :

song_titleaverage_streams_per_songdateaverage_streams_per_datediff_from_daily_average
All Along the Watchtower8132023-01-011,031-21.14
Bold as Love7412023-01-011,031-28.13
Burning of the Midnight Lamp5832023-01-011,031-43.45
D.M.S.R.2432023-01-011,031-76.43
Do It All Night9542023-01-011,031-7.47

Les données montrent que le flux quotidien moyen pour le 1er janvier 2023 est de 1 031. "All Along the Watchtower" est 21,14 % en dessous de cette moyenne. Les deux chansons suivantes sont 28,13 % et 43,45 % en dessous de la moyenne quotidienne, et ainsi de suite.

5 : Calculer la rémunération moyenne la plus élevée et la plus basse pour un album, par artiste

Expliquons ce que nous entendons par là. Nous voulons d'abord trouver la rémunération moyenne par album et par date. Ensuite, nous devons trouver la rémunération la plus basse et la plus élevée par album. Ensuite, nous voulons agréger les données par artiste. En plus de son nom, nous devons afficher la valeur de la rémunération la plus basse que l'artiste a reçue pour un album. Nous devons faire de même avec la rémunération la plus élevée pour un album.

La solution dans SQL Server contient deux CTE. Cependant, il s'agit cette fois d'un CTE imbriqué. En effet, le deuxième CTE fait référence au premier CTE. Voyons comment cela fonctionne :

WITH pay_per_album AS (
  SELECT album_id,
	   date,
	   AVG(number_of_streams * pay_per_stream) AS average_pay_per_album
  FROM streams
  GROUP BY album_id, date
),
	
min_max_average_pay AS (
  SELECT album_id,
	   MIN(average_pay_per_album) AS lowest_average_pay_by_album,
	   MAX(average_pay_per_album) AS highest_average_pay_by_album
  FROM pay_per_album
  GROUP BY album_id
)

SELECT artist_name,
	 MIN(lowest_average_pay_by_album) AS lowest_album_pay_by_artist,
	 MAX(highest_average_pay_by_album) AS highest_album_pay_by_artist
FROM min_max_average_pay mmap
JOIN albums al
ON mmap.album_id = al.id
JOIN artist ar
ON al.artist_id = ar.id
GROUP BY artist_name;

Faites attention lorsque vous lisez l'explication du code ! Il est facile de se perdre dans toutes ces agrégations. Pour faciliter les choses, j'ai copié chaque partie de la requête et l'ai fait suivre d'une explication. Nous allons commencer par le premier CTE :

WITH pay_per_album AS (
  SELECT album_id,
	   date,
	   AVG(number_of_streams * pay_per_stream) AS average_pay_per_album
  FROM streams
  GROUP BY album_id, date
),

Le premier CTE calcule la rémunération moyenne par album et la date. Pour ce faire, on multiplie le nombre de streams par la rémunération par stream et on utilise AVG().

min_max_average_pay AS (
  SELECT album_id,
	   MIN(average_pay_per_album) AS lowest_average_pay_by_album,
	   MAX(average_pay_per_album) AS highest_average_pay_by_album
  FROM pay_per_album
  GROUP BY album_id
)

Lors de l'écriture du deuxième CTE dans SQL Server, la syntaxe est la même que dans l'exemple précédent - pas de WITH supplémentaire, commencez par le nom du CTE et séparez les CTE par une virgule. La seule différence est que, cette fois, le deuxième CTE fait référence au premier CTE, et non à l'ensemble de données d'origine.

Cet ETC imbriqué utilise les fonctions MIN() et MAX() pour trouver la rémunération moyenne la plus basse et la plus élevée de chaque album pour toutes les dates. Le premier CTE est référencé dans la fonction FROM.

SELECT artist_name,
	 MIN(lowest_average_pay_by_album) AS lowest_album_pay_by_artist,
	 MAX(highest_average_pay_by_album) AS highest_album_pay_by_artist
FROM min_max_average_pay mmap
JOIN albums al
ON mmap.album_id = al.id
JOIN artist ar
ON al.artist_id = ar.id
GROUP BY artist_name;

Enfin, le site SELECT relie le deuxième CTE avec les fonctions albums et artist . Nous appliquons à nouveau les fonctions MIN() et MAX() au résultat du deuxième CTE. Il s'agit de renvoyer uniquement les valeurs de l'album le moins payé et de l'album le plus payé de tous les albums de chaque artiste.

Voici ce que nous obtenons après avoir exécuté la requête :

artist_namelowest_album_pay_by_artisthighest_album_pay_by_artist
Jimi Hendrix1.5963.19
Prince4.6497.31
Santana0.9110.22

6 : Trouver le chemin le plus long entre Rotterdam et Amsterdam

Il s'agit d'une variante du problème du plus court chemin dans la théorie des graphes, sauf que nous chercherons le chemin le plus long.

Un graphe est un type de structure de données composé de nœuds ou de points reliés par des arêtes. Comme ils sont connectés, il est possible de trouver un chemin d'un nœud à l'autre, même s'ils ne sont pas directement connectés.

Il s'agit d'une carte des routes. C'est exactement l'exemple que nous allons utiliser ici. Voici le tableau cities_distancequi montre les villes et la distance qui les sépare. Utilisez cette requête pour créer le tableau, qui contient les colonnes suivantes :

  • city_from - La ville d'origine.
  • city_to - La ville d'arrivée.
  • distance - La distance entre les deux villes, en kilomètres.

Voici les données :

city_fromcity_todistance
RotterdamAmsterdam78.20
RotterdamGouda24.10
AmsterdamGouda72.50
GoudaLeiden34.10
AmsterdamLeiden50.00
RotterdamLeiden35.40
GoudaUtrecht44.00
UtrechtAmsterdam52.40
LeidenGouda34.10

Nous devons trouver le chemin le plus long entre Rotterdam et Amsterdam. Le chemin doit inclure le nom de toutes les villes situées sur le trajet, séparées par des '/'. Nous devons également indiquer la longueur du chemin le plus long.

Lorsque nous parlons du chemin le plus long, nous voulons exclure les chemins circulaires (où l'on peut faire des tours à l'infini et augmenter la distance). Nous voulons que ce chemin le plus long ne passe qu'une seule fois par une ville donnée.

Pour résoudre ce problème, nous utiliserons un CTE récursif. Il s'agit d'une requête qui se réfère à elle-même jusqu'à ce qu'elle atteigne la fin des données. Cette caractéristique est idéale pour l'interrogation de données graphiques, où plusieurs chemins peuvent mener au même objectif.

Voyons comment fonctionne cet ETC récursif :

WITH longest_path AS (
  SELECT cd.city_to,
         CAST((cd.city_from + '/' + cd.city_to) AS VARCHAR(100)) AS path,
        cd.distance AS distance
   FROM cities_distance cd
   WHERE cd.city_from = 'Rotterdam'

UNION ALL

  SELECT cd.city_to,
         CAST((lp.path + '/' + cd.city_to) AS VARCHAR(100)) AS path,
         CAST((lp.distance + cd.distance) AS DECIMAL(10,2))
  FROM longest_path lp 
  INNER JOIN cities_distance cd
  ON cd.city_from = lp.city_to
  WHERE lp.city_to <> 'Amsterdam'
  AND lp.path NOT LIKE '%/' + cd.city_to + '/%'
)

SELECT TOP 1 lp.path,
	 lp.distance
FROM longest_path lp
WHERE lp.city_to = 'Amsterdam'
ORDER BY lp.distance DESC;

La syntaxe est la même que précédemment - la requête récursive commence également par WITH dans SQL Server.

Comme d'habitude, il y a une déclaration SELECT entre parenthèses. Il y en a deux, pour être plus précis. Voyons ce que fait la première.

WITH longest_path AS (
  SELECT cd.city_to,
         CAST((cd.city_from + '/' + cd.city_to) AS VARCHAR(100)) AS path,
         cd.distance AS distance
  FROM cities_distance cd
  WHERE cd.city_from = 'Rotterdam'

Le premier SELECT dans la récursion est appelé le membre d'ancrage. Il est utilisé pour sélectionner le point de départ de la récursion. Le point de départ sera Rotterdam, que nous obtenons en filtrant cette ville dans WHERE. La colonne city_to est utilisée pour afficher toutes les destinations finales qui peuvent être atteintes directement à partir de Rotterdam. La colonne path énumère toutes les villes d'origine et de destination. La longueur de cet itinéraire est indiquée dans la colonne distance.

Vient ensuite UNION ALL, qui relie les résultats de l'ancre et du membre récursif, c'est-à-dire le second SELECT. L'union de ces deux requêtes est nécessaire pour que la récursivité fonctionne.

Remarque : dans certains autres dialectes SQL, il est également possible d'utiliser UNION. Cependant, SQL Server n'autorise que UNION ALL.

Nous en arrivons maintenant au membre récursif. Il fait référence à l'ETC lui-même dans FROM et le joint à la table cities_distance. Pour que les requêtes soient unifiées, elles doivent toutes deux avoir le même nombre de colonnes du même type de données. Les deux premières colonnes sont les mêmes que dans le membre d'ancrage. La colonne longest_path additionne toutes les distances parcourues pour atteindre toutes les villes à partir de Rotterdam.

SELECT cd.city_to,
       CAST((lp.path + '/' + cd.city_to) AS VARCHAR(100)) AS path,
       CAST((lp.distance + cd.distance) AS DECIMAL(10,2))
FROM longest_path lp 
INNER JOIN cities_distance cd
ON cd.city_from = lp.city_to
WHERE lp.city_to <> 'Amsterdam'
AND lp.path NOT LIKE '%/' + cd.city_to + '/%'
)

Nous avons également ajouté deux conditions dans WHERE. La première exclut toutes les relations où Amsterdam est la destination finale ; nous recherchons le chemin le plus long, et non le plus court, vers Amsterdam. La deuxième condition garantit que toute nouvelle ville ajoutée au chemin n'est pas déjà incluse dans le chemin. Dans le cas contraire, la requête entrera dans une récursivité sans fin. Cela répond à ce que nous avons dit plus haut : le chemin le plus long ne doit pas visiter la même ville plus d'une fois.

Pour mieux comprendre ce dont nous parlons, voici la sortie de l'ETC récursif :

city_topathdistance
AmsterdamRotterdam/Amsterdam78.20
GoudaRotterdam/Gouda24.10
LeidenRotterdam/Leiden35.40
GoudaRotterdam/Leiden/Gouda69.50
UtrechtRotterdam/Leiden/Gouda/Utrecht113.50
AmsterdamRotterdam/Leiden/Gouda/Utrecht/Amsterdam165.90
LeidenRotterdam/Gouda/Leiden58.2
UtrechtRotterdam/Gouda/Utrecht68.1
AmsterdamRotterdam/Gouda/Utrecht/Amsterdam120.5

Vous pouvez constater qu'il existe trois chemins entre Rotterdam et Amsterdam. L'un est direct, avec une distance de 78,20 km. Le deuxième et le troisième passent par d'autres villes et prennent respectivement 165,90 et 120,50 km.

Attention, il ne s'agit pas du résultat final ! Notre solution comporte également une instruction SELECT qui fait référence à l'ETC :

SELECT TOP 1 lp.path,
	 lp.distance
FROM longest_path lp
WHERE lp.city_to = 'Amsterdam'
ORDER BY lp.distance DESC;

Ce site SELECT renvoie le chemin et la distance. Nous utilisons la commande TOP 1 combinée à ORDER BY pour obtenir le chemin le plus long entre Rotterdam et Amsterdam. Nous avons trié les données de la distance la plus élevée à la plus courte, de sorte que la première ligne correspondra également au chemin le plus long.

Voici le résultat final :

pathdistance
Rotterdam/Leiden/Gouda/Utrecht/Amsterdam165.90

Ce résultat montre que le chemin le plus long de Rotterdam à Amsterdam est de 165,9 km et passe par Leiden, Gouda et Utrecht.

Si vous ne vous lassez pas de ce sujet, voici d'autres exemples d'ETC.

Quand utiliser les CTE ?

Comme vous l'avez vu dans nos exemples, un CTE a de nombreuses fonctions dans SQL Server.

L'un d'entre eux est qu'il améliore généralement la lisibilité du code. Toutes les solutions ci-dessus (à l'exception de la récursion) auraient pu être écrites avec des sous-requêtes. Mais le code serait alors beaucoup plus long et moins clair.

À bien y réfléchir, les sous-requêtes sont généralement écrites à l'encontre de la logique du problème que vous essayez de résoudre. Vous avez d'abord la requête principale, qui utilise la sortie de la sous-requête. La sous-requête est donc généralement la première étape du calcul, même si elle n'est pas positionnée de cette manière dans le code.

Les CTE, en revanche, peuvent être écrits de manière à suivre la logique du problème. Vous pouvez écrire plusieurs CTE distincts et fusionner leurs résultats dans les instructions SELECT. Vous pouvez également faire référence à la sortie d'un CTE avec la deuxième requête (ou la troisième, la quatrième...), l'instruction SELECT finale constituant un autre niveau de calcul.

L'un des exemples montre également qu'il est possible de classer des données dans SQL Server à l'aide d'une fonction window et d'un CTE.

Si vous souhaitez écrire des requêtes récursives dans SQL Server, vous ne pouvez pas le faire sans CTE. Un CTE peut être non récursif, mais aucune requête récursive n'existe sans CTE. Outre les graphes, la récursivité est extrêmement utile pour interroger les structures hiérarchiques, telles que l'organisation des données et les arbres généalogiques.

Pour en savoir plus sur l'utilisation d'un ETC, cliquez ici.

Les ETC sont la porte d'entrée vers l'utilisation de SQL avancé!

Les CTE sont l'un des concepts les plus avancés de SQL Server. Si vous voulez accéder à des compétences SQL Server de niveau avancé, les CTE sont indispensables.

Au fur et à mesure que vos requêtes dans SQL Server deviennent plus complexes, vous vous rendrez compte que l'apprentissage des CTE a été l'une des meilleures décisions que vous ayez jamais prises. Ils constituent également un tremplin vers les requêtes récursives, vous permettant d'interroger des types inhabituels de structures de données dans SQL Server, tels que les hiérarchies et les graphiques.

Cet article n'est qu'un aperçu des connaissances que vous trouverez dans le cours Requêtes récursives in MS SQL Server. Ne vous arrêtez donc pas là. Il y a encore beaucoup à apprendre !