+1 para Erik, mas queria adicionar duas coisas (que não funcionaram bem em um comentário):
Você nem precisa olhar para os planos de execução para ver que eles são ignorados quando não são usados. O seguinte deve produzir um erro "dividir por 0", mas não devido a cte2não ter sido selecionado:
;WITH cte1 AS
(
SELECT 1 AS [Bob]
),
cte2 AS (
SELECT 1 / 0 AS [Err]
FROM cte1
)
SELECT *
FROM cte1;
Os CTEs podem ser ignorados, mesmo que sejam os únicos CTE, e mesmo que sejam selecionados, se logicamente todas as linhas forem excluídas de qualquer maneira. O seguinte é um caso em que o otimizador de consulta sabe com antecedência que nenhuma linha pode ser retornada do CTE, então ele nem se preocupa em executá-lo:
;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;
Em relação ao desempenho, o CTE não utilizado é analisado e compilado (ou pelo menos compilado no caso abaixo), portanto não é 100% ignorado, mas o custo teria que ser insignificante e não vale a pena se preocupar.
Ao analisar apenas, não há erro:
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
Ao fazer tudo pouco antes da execução, há um 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'.
*/
Parece que não, mas isso realmente só se aplica a CTEs aninhados.
Crie duas tabelas temporárias:
CREATE TABLE #t1 (id INT);
INSERT #t1 ( id )
VALUES ( 1 );
CREATE TABLE #t2 (id INT);
INSERT #t2 ( id )
VALUES ( 1 );
Pergunta 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;
Pergunta 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;
Planos de consulta:
Há uma sobrecarga, mas a parte desnecessária da consulta é eliminada muito cedo (durante a análise neste caso; o estágio de simplificação em casos mais complexos), de modo que o trabalho adicional é realmente mínimo e não contribui para custos potencialmente caros. otimização.
+1 para Erik, mas queria adicionar duas coisas (que não funcionaram bem em um comentário):
Você nem precisa olhar para os planos de execução para ver que eles são ignorados quando não são usados. O seguinte deve produzir um erro "dividir por 0", mas não devido a
cte2
não ter sido selecionado:Os CTEs podem ser ignorados, mesmo que sejam os únicos CTE, e mesmo que sejam selecionados, se logicamente todas as linhas forem excluídas de qualquer maneira. O seguinte é um caso em que o otimizador de consulta sabe com antecedência que nenhuma linha pode ser retornada do CTE, então ele nem se preocupa em executá-lo:
Em relação ao desempenho, o CTE não utilizado é analisado e compilado (ou pelo menos compilado no caso abaixo), portanto não é 100% ignorado, mas o custo teria que ser insignificante e não vale a pena se preocupar.
Ao analisar apenas, não há erro:
Ao fazer tudo pouco antes da execução, há um problema:
Parece que não, mas isso realmente só se aplica a CTEs aninhados.
Crie duas tabelas temporárias:
Pergunta 1:
Pergunta 2:
Planos de consulta:
Há uma sobrecarga, mas a parte desnecessária da consulta é eliminada muito cedo (durante a análise neste caso; o estágio de simplificação em casos mais complexos), de modo que o trabalho adicional é realmente mínimo e não contribui para custos potencialmente caros. otimização.