Jawaban:
Tampaknya tidak demikian, tetapi ini hanya berlaku untuk CTE bersarang.
Buat dua tabel temp:
CREATE TABLE #t1 (id INT);
INSERT #t1 ( id )
VALUES ( 1 );
CREATE TABLE #t2 (id INT);
INSERT #t2 ( id )
VALUES ( 1 );
Pertanyaan 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;
Pertanyaan 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;
Paket pertanyaan:
Ada overhead, tetapi bagian yang tidak perlu dari query dihilangkan sangat awal (selama parsing dalam kasus ini; tahap penyederhanaan dalam kasus yang lebih kompleks), sehingga pekerjaan tambahan benar-benar minimal, dan tidak berkontribusi terhadap potensi biaya berbasis biaya optimasi.
+1 ke Erik, tetapi ingin menambahkan dua hal (yang tidak berfungsi dengan baik dalam komentar):
Anda bahkan tidak perlu melihat rencana eksekusi untuk melihat bahwa mereka diabaikan ketika tidak digunakan. Berikut ini akan menghasilkan kesalahan "bagi dengan 0" tetapi tidak karena cte2
tidak dipilih sama sekali:
;WITH cte1 AS
(
SELECT 1 AS [Bob]
),
cte2 AS (
SELECT 1 / 0 AS [Err]
FROM cte1
)
SELECT *
FROM cte1;
CTE dapat diabaikan, bahkan jika mereka adalah satu-satunya CTE, dan bahkan jika mereka dipilih dari, jika secara logis semua baris akan dikecualikan. Berikut ini adalah kasus di mana pengoptimal kueri tahu sebelumnya bahwa tidak ada baris yang dapat dikembalikan dari CTE, sehingga tidak perlu repot untuk mengeksekusinya:
;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;
Mengenai kinerja, CTE yang tidak digunakan diuraikan dan dikompilasi (atau setidaknya dikompilasi dalam kasus di bawah), sehingga tidak diabaikan 100%, tetapi biaya harus diabaikan dan tidak layak untuk dikhawatirkan.
Saat hanya parsing, tidak ada kesalahan:
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
Ketika melakukan semuanya hanya untuk eksekusi, maka ada masalah:
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()
pandangan untuk digunakan dalam UDF dapat mengembalikan nilai yang sama dari beberapa panggilan karena optimizer caching.