Respuestas:
No parece que lo hagan, pero esto realmente solo se aplica a los CTE anidados.
Crea dos tablas temporales:
CREATE TABLE #t1 (id INT);
INSERT #t1 ( id )
VALUES ( 1 );
CREATE TABLE #t2 (id INT);
INSERT #t2 ( id )
VALUES ( 1 );
Consulta 1:
WITH your_mom AS (
SELECT TOP 1 *
FROM #t1 AS t
),
also_your_mom AS (
SELECT TOP 1 *
FROM #t2 AS t
)
SELECT *
FROM your_mom;
Consulta 2:
WITH your_mom AS (
SELECT TOP 1 *
FROM #t1 AS t
),
also_your_mom AS (
SELECT TOP 1 *
FROM #t2 AS t
)
SELECT *
FROM also_your_mom;
Planes de consulta:
Hay una sobrecarga, pero la parte innecesaria de la consulta se elimina muy pronto (durante el análisis en este caso; la etapa de simplificación en casos más complejos), por lo que el trabajo adicional es realmente mínimo y no contribuye a costos potencialmente costosos. mejoramiento.
+1 a Erik, pero quería agregar dos cosas (que no funcionaron bien en un comentario):
Ni siquiera necesita mirar los planes de ejecución para ver que se ignoran cuando no se usan. Lo siguiente debería producir un error "dividir por 0" pero no se debe a que cte2
no se haya seleccionado en absoluto:
;WITH cte1 AS
(
SELECT 1 AS [Bob]
),
cte2 AS (
SELECT 1 / 0 AS [Err]
FROM cte1
)
SELECT *
FROM cte1;
Los CTE se pueden ignorar, incluso si son los únicos CTE, e incluso si se seleccionan de ellos, si lógicamente todas las filas se excluirían de todos modos. El siguiente es un caso en el que el optimizador de consultas sabe de antemano que no se pueden devolver filas del CTE, por lo que ni siquiera se molesta en ejecutarlo:
;WITH cte AS
(
SELECT 1 / 0 AS [Bob]
)
SELECT TOP (1) [object_id]
FROM sys.objects
UNION ALL
SELECT cte.[Bob]
FROM cte
WHERE 1 = 0;
En cuanto al rendimiento, el CTE no utilizado se analiza y compila (o al menos se compila en el caso a continuación), por lo que no se ignora al 100%, pero el costo debería ser insignificante y no merece la pena preocuparse.
Cuando solo se analiza, no hay error:
SET PARSEONLY ON;
;WITH cte1 AS
(
SELECT obj.[NotHere]
FROM sys.objects obj
)
SELECT TOP (1) so.[name]
FROM sys.objects so
GO
SET PARSEONLY OFF;
GO
Al hacer todo justo antes de la ejecución, entonces hay un problema:
GO
SET NOEXEC ON;
GO
;WITH cte1 AS
(
SELECT obj.[NotHere]
FROM sys.objects obj
)
SELECT TOP (1) so.[name]
FROM sys.objects so
GO
SET NOEXEC OFF;
GO
/*
Msg 207, Level 16, State 1, Line XXXXX
Invalid column name 'NotHere'.
*/
NEWID()
una vista para usar en un UDF puede devolver el mismo valor de múltiples llamadas debido al caché del optimizador.