Différence entre CTE et SubQuery?

A partir de ce post comment utiliser ROW_NUMBER dans la procédure suivante?

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

maintenant, quel est L'avantage d'utiliser un CTE (Common Table Expression) sur un s ub-query (ainsi, plus lisible ce que la requête fait réellement)

le seul avantage d'utiliser un CTE par rapport à la sous-sélection est que je peux réellement nom la sous-requête. Y a-t-il d'autres différences entre ces deux lorsqu'un ETC est utilisé comme un ETC simple (non récursif)?

116
demandé sur DineshDB 2009-04-01 23:18:15

9 réponses

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

In general ; un CTE peut être utilisé de façon récursive; une sous-requête ne peut pas. Cela les rend particulièrement bien adaptés aux structures d'arbres.

82
répondu Marc Gravell 2009-04-01 19:21:09

le principal avantage de la expression courante de la Table (lorsque vous ne l'utilisez pas pour requêtes récursives ) est l'encapsulation, au lieu d'avoir à déclarer la sous-requête à chaque endroit que vous souhaitez l'utiliser, vous êtes en mesure de la définir une fois, mais ont des références multiples à elle.

Toutefois, cela ne pas signifie qu'elle n'est exécutée qu'une seule fois (comme pour des itérations précédentes de cette réponse , merci à tous ceux qui ont commenté). La requête a certainement le potentiel d'être exécutée plusieurs fois si référencée plusieurs fois; l'optimiseur de requête prend finalement la décision de comment le CTE devrait être interprété.

74
répondu casperOne 2017-05-23 11:55:13

CTE 's 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 lignes (jusqu'à 101 ). Utile pour les calendriers, les faux ensembles de rangements, etc.

ils sont aussi plus lisibles (à mon avis).

en dehors de cela, CTE et subqueries sont identiques.

15
répondu Quassnoi 2015-11-16 14:05:39

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

9
répondu user340140 2012-02-19 01:59:42

à moins que je ne manque quelque chose, vous pouvez nommer CTE et les sous-séries aussi facilement.

je suppose que la principale différence est la lisibilité (je trouve le CTE plus lisible parce qu'il définit votre sous-commande à l'avant plutôt qu'au milieu).

et si vous avez besoin de faire quoi que ce soit avec la récursion, vous allez avoir un peu de mal à le faire avec un subquery;)

8
répondu AlexCuse 2009-04-01 19:22:10

en ajoutant aux réponses des autres, si vous avez un seul et même sous-article Utilisé plusieurs fois, vous pouvez remplacer tous ces sous-Articles par un seul CTE. Cela vous permet de mieux RÉUTILISER votre code.

5
répondu A-K 2009-09-23 21:48:35

un fait important que personne n'a mentionné est que (au moins dans postgres), CTEs sont des clôtures d'optimisation:

https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences /

c'est-à-dire qu'ils seront traités comme leur propre requête atomique, plutôt que pliés dans l'ensemble du plan de requête. Je n'ai pas l'expertise pour donner une meilleure explication, mais vous devriez vérifier la sémantique pour la version de sql vous utilisez; pour les utilisateurs avancés, être en mesure de créer une barrière d'optimisation peut aider les performances si vous êtes niveau expert dans le contrôle planificateur de requête; dans 99% des cas, cependant, vous devriez éviter d'essayer de dire au planificateur de requête ce qu'il faut faire, parce que ce que vous pensez sera plus rapide est probablement pire que ce qu'il pense sera plus rapide. :- )

5
répondu Ajax 2017-08-03 23:55:28

une chose que vous devez également comprendre est que dans les anciennes versions de SQL Server (oui beaucoup de gens ont encore besoin de soutenir les bases de données SQL Server 2000), CTEs ne sont pas autorisés et puis la table dérivée est votre meilleure solution.

4
répondu HLGEM 2011-01-26 16:18:20

indice: (MAXRECURSION n)

vous pouvez limiter le nombre de niveaux de récursivité autorisés pour un déclaration en utilisant l'indice MAXRECURSION et une valeur entre 0 et de 32 767 dans le OPTION clause

par exemple, vous pouvez essayer:

OPTION 
      (MAXRECURSION 150)

GO
2
répondu Basic_ 2015-03-31 11:53:23