¿Diferencia entre CTE y SubQuery?

143

De esta publicación ¿Cómo usar ROW_NUMBER en el siguiente procedimiento?

Hay dos versiones de respuestas donde una usa ay sub-queryla otra usa a CTEpara resolver el mismo problema.

Ahora bien, ¿cuál es la ventaja de usar un CTE (Common Table Expression)sobre una 'subconsulta' (por lo tanto, es más legible lo que la consulta realmente está haciendo)

La única ventaja de usar un CTEover sub-selectes que realmente puedo nombrar el sub-query. ¿Hay alguna otra diferencia entre esos dos cuando se usa un CTE como un CTE simple (no recursivo)?

dance2die
fuente
Pregunta derivada con buena discusión: stackoverflow.com/q/11169550/781695
usuario
77
En mi opinión, cualquiera que piense que un CTE es menos legible que una gran cantidad de subconsultas entrelazadas no ha visto el montón de consultas confusas en forma de dientes de sierra en uso en la mayoría de los sistemas de gestión de datos empresariales. Las consultas grandes, no triviales, son típicamente mucho más fáciles de leer más tarde o por medio de nuevos ojos que las subconsultas, y al menos en el caso de Postgres, el rendimiento mágico es mucho mejor en muchos casos. ([Por razones que todavía tengo que entender [( stackoverflow.com/questions/33731068/… ), ya que lo contrario parece más probable).
zxq9

Respuestas:

102

En las versiones CTE de subconsulta versus versiones simples (no recursivas), probablemente sean muy similares. Tendría que usar el generador de perfiles y el plan de ejecución real para detectar cualquier diferencia, y eso sería específico para su configuración (por lo que no podemos decirle la respuesta completa).

En general ; Un CTE puede usarse recursivamente; una subconsulta no puede Esto los hace especialmente adecuados para estructuras de árboles.

Marc Gravell
fuente
1
Lo siento, debería haber sido más claro en mi pregunta. ¿Cuál sería la diferencia entre CTE y Subconsulta en el contexto donde se usa CTE como subconsulta?
dance2die 01 de
2
@Marc Gravell: Sin embargo, podemos hacer más que eso, ya que el comportamiento del generador de perfiles no está garantizado, frente al comportamiento del CTE, que es (en términos de evaluación).
casperOne
1
No estoy seguro de cuánto tiene sentido esta declaración para las personas que miran el CTS y la diferencia de subconsulta A CTE can be used recursively; a sub-query cannot. Un ejemplo hubiera sido genial.
Aniket Thakur
88

La principal ventaja de la expresión de tabla común (cuando no se usa para consultas recursivas ) es la encapsulación, en lugar de tener que declarar la subconsulta en cada lugar donde desee usarla, puede definirla una vez, pero tiene múltiples referencias lo.

Sin embargo, esto no significa que se ejecute solo una vez (según las iteraciones anteriores de esta misma respuesta , gracias a todos los que han comentado). La consulta definitivamente tiene el potencial de ejecutarse varias veces si se hace referencia a ella varias veces; el optimizador de consultas finalmente toma la decisión de cómo se debe interpretar el CTE.

casperOne
fuente
"Pensar en un CTE como una variable de tabla temporal" ¿eso significa que el CTE se almacena en el disco o en la memoria?
dance2die 01 de
No puede utilizar el CTE o la subconsulta en múltiples consultas, por definición. Estoy bastante seguro de que el optimizador maneja la subconsulta de la misma manera que manejaría el CTE (evaluando el conjunto de resultados solo una vez, independientemente de cuántas veces se use dentro de la consulta 1)
AlexCuse
@AlexCuse: Creo que he aclarado el contexto del CTE lo suficiente, pero agregué más para intentar aclarar más.
casperOne
@AlexCuse: tampoco hay implicación de que el CTE o la subconsulta se puedan usar en varios lugares. Sin embargo, la diferencia entre el CTE y el optimizador es que el comportamiento del CTE está garantizado, mientras que el comportamiento del optimizador no.
casperOne
y admitiré que podría haber algunos casos extremos en los que el optimizador se ahoga y la subconsulta se evalúa más de una vez, aunque no me he encontrado con ninguno. Por otra parte, uso CTE siempre que puedo;)
AlexCuse
15

CTELos más útiles para la recursividad:

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

devolverá @nfilas (hasta 101). Útil para calendarios, conjuntos de filas ficticias, etc.

También son más legibles (en mi opinión).

Aparte de esto, CTE'S y subqueriesson idénticos.

Quassnoi
fuente
En MSSQL, debe agregar un punto y coma (;) antes de WITH, en orden, obtendrá un error. debería ser;WITH blabla AS ...)
Obinna Nnenanya
2
@ObinnaNnenanya: solo si no es la primera declaración del lote. Terminando sus declaraciones con punto y coma es una idea buena de todos modos, a pesar de que SQL Server no fuerza que en las versiones actuales de otros que antes WITH, MERGEy similares
Quassnoi
10

Una diferencia que no se ha mencionado es que se puede hacer referencia a un solo CTE en varias partes de un sindicato

usuario340140
fuente
8

A menos que me falte algo, puede nombrar CTE y subconsultas con la misma facilidad.

Supongo que la principal diferencia es la legibilidad (encuentro que el CTE es más legible porque define su subconsulta por adelantado en lugar de en el medio).

Y si necesita hacer algo con la recursividad, tendrá algunos problemas para hacerlo con una subconsulta;)

AlexCuse
fuente
1
No estoy seguro de que haya alguna diferencia no estética (aunque espero que en ciertas situaciones pueda haber ligeras diferencias en el plan de ejecución). ¿Te importaría iluminarme?
AlexCuse
2
Puede nombrar CTE, pero solo puede alias subconsultas. La diferencia es que puede reutilizar los CTE con múltiples alias (véase el ejemplo de @Michael Petito en su comentario a casperOne). No sé de ninguna manera de hacer eso con subconsultas.
kmote
7

Un hecho importante que nadie ha mencionado es que (al menos en postgres), los CTE son vallas de optimización:

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

Es decir, serán tratados como su propia consulta atómica, en lugar de plegarse en todo el plan de consulta. Me falta la experiencia para dar una mejor explicación, pero debe verificar la semántica de la versión de sql que está utilizando; para usuarios avanzados, poder crear una valla de optimización puede ayudar al rendimiento si tiene un nivel experto en el control del planificador de consultas; en el 99% de los casos, sin embargo, debe evitar intentar decirle al planificador de consultas qué hacer, porque lo que cree que será más rápido es probablemente peor de lo que cree que será más rápido. :-)

Ajax
fuente
6

Agregando a las respuestas de otros, si tiene una y la misma subconsulta utilizada varias veces, puede reemplazar todas estas subconsultas con un CTE. Esto le permite reutilizar mejor su código.

Alaska
fuente
4

Una cosa que debe comprender también es que en versiones anteriores de SQL Server (sí, muchas personas aún necesitan admitir bases de datos SQL Server 2000), los CTE no están permitidos y la tabla derivada es su mejor solución.

HLGEM
fuente
2

SUGERENCIA: (MAXRECURSION n)

puede limitar el número de niveles de recursión permitidos para una declaración específica utilizando la MAXRECURSIONsugerencia y un valor entre 0 y 32,767 en la OPTIONcláusula

Por ejemplo, podrías probar:

OPTION 
      (MAXRECURSION 150)

GO
Básico_
fuente