gpt4 book ai didi

sql - SQL Server 2005 中 CTE 的评估

转载 作者:行者123 更新时间:2023-12-03 03:09:50 25 4
gpt4 key购买 nike

我有一个关于 MS SQL 如何评估 CTE 内的函数的问题。几次搜索没有找到与此问题相关的任何结果,但如果这是常识并且我只是落后于潮流,我深表歉意。这不是第一次了:-)

这个查询是我实际正在做的事情的简化(并且显然不太动态)版本,但它确实展示了我遇到的问题。它看起来像这样:

CREATE TABLE #EmployeePool(EmployeeID int, EmployeeRank int);

INSERT INTO #EmployeePool(EmployeeID, EmployeeRank)
SELECT 42, 1
UNION ALL
SELECT 43, 2;

DECLARE @NumEmployees int;
SELECT @NumEmployees = COUNT(*) FROM #EmployeePool;

WITH RandomizedCustomers AS (
SELECT CAST(c.Criteria AS int) AS CustomerID,
dbo.fnUtil_Random(@NumEmployees) AS RandomRank
FROM dbo.fnUtil_ParseCriteria(@CustomerIDs, 'int') c)
SELECT rc.CustomerID,
ep.EmployeeID
FROM RandomizedCustomers rc
JOIN #EmployeePool ep ON ep.EmployeeRank = rc.RandomRank;

DROP TABLE #EmployeePool;

对于上述所有执行,可以假设以下内容:

  • dbo.fnUtil_Random() 的结果始终是一个大于零且小于或等于传入参数的 int 值。因为上面使用 @ 调用它NumEmployees 的值为 2,该函数的计算结果始终为 1 或 2。

  • dbo.fnUtil_ParseCriteria(@CustomerIDs, 'int') 的结果生成一个单列单行表,其中包含基本类型为 'int' 的 sql_variant值为 219935。

鉴于上述假设,上面表达式的结果应该始终生成一个包含一条记录(CustomerID 和 EmployeeID)的两列表,这是有道理的(无论如何,对我来说)。 CustomerID 应始终为 int 值 219935,EmployeeID 应为 42 或 43。

但是,情况并非总是如此。有时我会得到预期的单曲记录。有时我会得到两条记录(每个 EmployeeID 一条),还有一些时候我没有得到任何记录。但是,如果我用真正的临时表替换 RandomizedCustomers CTE,问题就会完全消失。

每次我认为我对这种行为有一个解释时,结果证明它没有意义或不可能,所以我实际上无法解释为什么会发生这种情况。由于当我用临时表替换 CTE 时不会发生问题,因此我只能假设它与在连接到该 CTE 期间评估 CTE 内的函数有关。你们有什么理论吗?

最佳答案

SQL Server 的优化器可以自由决定是否重新评估CTE

例如,这个查询:

WITH    q AS
(
SELECT NEWID() AS n
)
SELECT *
FROM q
UNION ALL
SELECT *
FROM q

将生成两个不同的 NEWID(),但是,如果您使用缓存的 XML 计划将 CTE 包装到 >Eager Spool操作,记录将是相同的。

关于sql - SQL Server 2005 中 CTE 的评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2524072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com