169 votes

Différence entre CTE et SubQuery ?

De ce poste Comment utiliser ROW_NUMBER dans la procédure suivante ?

Il existe deux versions de réponses où l'une utilise un sub-query et l'autre utilise un CTE pour résoudre le même problème.

Alors, quel est l'avantage d'utiliser un CTE (Common Table Expression) sur une "sous-requête" (donc, plus de lisible ce que la requête fait réellement)

Le seul avantage de l'utilisation d'un CTE sur sub-select c'est que je peux en fait nom le site sub-query . Y a-t-il d'autres différences entre ces deux lorsqu'un CTE est utilisé comme un CTE simple (non récurrent) ?

0 votes

Question dérivée avec une bonne discussion : stackoverflow.com/q/11169550/781695

10 votes

IMO, toute personne qui pense qu'un CTE est moins lisible qu'un gigantesque blob de sous-requêtes entrelacées n'a pas vu le tas d'ordures de requêtes confuses en forme de dents de scie utilisé dans la majorité des systèmes de gestion de données d'entreprise. Les grandes requêtes non triviales sont généralement beaucoup plus faciles à lire plus tard ou par de nouveaux yeux que les sous-requêtes et, au moins dans le cas de Postgres, elles sont magiquement performantes. beaucoup mieux dans de nombreux cas. ([Pour des raisons que je n'ai pas encore comprises[( stackoverflow.com/questions/33731068/ ), car le contraire semble plus probable).

119voto

Marc Gravell Points 482669

Dans la sous-requête vs simple (non récursif) CTE, elles sont probablement très similaires. Vous devrez utiliser le profileur et le plan d'exécution réel pour repérer les différences éventuelles, et cela sera spécifique à votre configuration (nous ne pouvons donc pas vous donner la réponse complète).

En général Un CTE peut être utilisé de manière récursive, ce qui n'est pas le cas d'une sous-requête. Cela les rend particulièrement bien adaptés aux structures arborescentes.

1 votes

Désolé, j'aurais dû être plus clair dans ma question. Quelle serait la différence entre CTE et Subquery dans le contexte où CTE est utilisé LIKE subquery ?

2 votes

@Marc Gravell : Nous pouvons faire plus que cela cependant, car le comportement du profileur n'est pas garanti, par rapport au comportement du CTE, qui l'est (en termes d'évaluation).

3 votes

Je ne suis pas sûr que cette déclaration ait un sens pour les personnes qui étudient les différences entre les CTS et les sous-requêtes. A CTE can be used recursively; a sub-query cannot . Un exemple aurait été formidable.

99voto

casperOne Points 49736

Le principal avantage de la Expression commune du tableau (lorsqu'il n'est pas utilisé pour les requêtes récursives ) est l'encapsulation. Au lieu de devoir déclarer la sous-requête à chaque endroit où vous souhaitez l'utiliser, vous pouvez la définir une fois, mais y faire référence plusieurs fois.

Cependant, cela ne no signifie qu'elle n'est exécutée qu'une seule fois (conformément à les itérations précédentes de cette même réponse (merci à tous ceux qui ont fait des commentaires). La requête a certainement le potentiel d'être exécutée plusieurs fois si elle est référencée plusieurs fois ; l'optimiseur de requête prend finalement la décision quant à comment le CTE doit être interprété.

1 votes

"Pensez à un CTE comme à une variable de table temporaire". Cela signifie-t-il que le CTE est stocké sur le disque ou en mémoire ?

1 votes

Par définition, vous ne pouvez pas utiliser le CTE ou la sous-requête dans plusieurs requêtes. Je suis presque sûr que l'optimiseur traite la sous-requête de la même manière que l'élément de transfert de données (en évaluant le jeu de résultats une seule fois, quel que soit le nombre de fois où il est utilisé dans la même requête).

0 votes

@AlexCuse : Je pense avoir suffisamment clarifié le contexte de la CTE, mais j'en ai rajouté pour essayer de clarifier davantage.

17voto

Quassnoi Points 191041

CTE sont les plus utiles pour la récursion :

WITH hier(cnt) AS (
        SELECT  1
        UNION ALL
        SELECT  cnt + 1
        FROM    hier
        WHERE   cnt < @n
        )
SELECT  cnt
FROM    hier

retournera @n rangs (jusqu'à 101 ). Utile pour les calendriers, les séries de lignes fictives, etc.

Ils sont également plus lisibles (à mon avis).

En dehors de cela, CTE et subqueries sont identiques.

0 votes

Dans MSSQL, vous devez ajouter un point-virgule ( ;) avant WITH, sinon vous obtiendrez une erreur. cela devrait être ;WITH blabla AS ...)

3 votes

@ObinnaNnenanya : seulement si ce n'est pas la première déclaration du lot. Terminer vos déclarations avec des points-virgules est une bonne idée de toute façon, même si SQL Server ne l'applique pas dans les versions actuelles autres qu'avant WITH , MERGE et similaires

11voto

user340140 Points 204

Une différence qui n'a pas été mentionnée est qu'un seul CTE peut être référencé dans les différentes parties d'une union.

8voto

AlexCuse Points 9823

Sauf erreur de ma part, vous pouvez nommer les CTE et les sous-requêtes tout aussi facilement.

Je pense que la principale différence est la lisibilité (je trouve le CTE plus lisible parce qu'il définit votre sous-requête en amont plutôt qu'au milieu).

Et si vous avez besoin de faire quelque chose avec la récursion, vous allez avoir un peu de mal à le faire avec une sous-requête ;)

1 votes

Je ne suis pas sûr qu'il y ait cualquier différence non esthétique (bien que je m'attende à ce que, dans certaines situations, il y ait de légères différences dans le plan d'exécution). Vous voulez m'éclairer ?

2 votes

Vous pouvez nom CTE, mais vous pouvez seulement alias sous-requêtes. La différence est que vous pouvez réutiliser les CTE avec plusieurs alias (cf. l'exemple de @Michael Petito dans son commentaire à casperOne). Je ne connais pas de moyen de faire cela avec les sous-requêtes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X