Sql server SQL Server 2008 R2设备的零缺陷

Sql server SQL Server 2008 R2设备的零缺陷,sql-server,sql-server-2008-r2,Sql Server,Sql Server 2008 R2,请告诉我,如果我错过了什么,如果我正在失去理智 下面的查询生成一个Device by zero错误 DECLARE @Test TABLE( ID INT, Val FLOAT ) INSERT INTO @Test SELECT 1, 0 ;WITH Grouped AS ( SELECT ID, Val, SUM(Val) OVER (PARTITION BY ID) T

请告诉我,如果我错过了什么,如果我正在失去理智

下面的查询生成一个Device by zero错误

DECLARE @Test TABLE(
        ID INT,
        Val FLOAT
)

INSERT INTO @Test SELECT 1, 0

;WITH   Grouped AS (
        SELECT  ID,
                Val,
                SUM(Val) OVER (PARTITION BY ID) TotalVal
        FROM    @Test
)
, Filtered AS (
        SELECT  *
        FROM    Grouped
        WHERE   TotalVal != 0
)
SELECT  *
FROM    Filtered
WHERE   Val / TotalVal > 0.05
其中,如下所示不会产生相同的错误

DECLARE @Test TABLE(
        ID INT,
        Val FLOAT
)

INSERT INTO @Test SELECT 1, 0

;WITH   Grouped AS (
        SELECT  ID,
                Val,
                SUM(Val) OVER (PARTITION BY ID) TotalVal
        FROM    @Test
)
, Filtered AS (
        SELECT  *
        FROM    Grouped
        WHERE   TotalVal != 0
)
SELECT  *,
        Val / TotalVal Test
FROM    Filtered
通过查看估计的查询计划,第一个查询尝试将where子句优化为

[Val]/[Expr1004]>(5.000000000000000e-002) AND [Expr1004]<>(0.000000000000000e+000)
但这将违背CTE第二份声明的目的。

请对此进行投票

就我个人而言,我对SQL Server的工作方式很满意,因为它允许某种程度的优化来预先计算(简化)表达式,而不是将组件向前推到以后进行计算(即使在逻辑上是合理的)

至于您的查询,是的,过滤后的CTE是一个非事件,应该被滚动到最终查询中。这样写意味着你相信CTE是以某种方式被处理并缓存在内存中的。那不是真的——请看另一个这样的问题。要进一步了解SQL Server的CTE实现,请访问。

转到此处并投票支持

就我个人而言,我对SQL Server的工作方式很满意,因为它允许某种程度的优化来预先计算(简化)表达式,而不是将组件向前推到以后进行计算(即使在逻辑上是合理的)


至于您的查询,是的,过滤后的CTE是一个非事件,应该被滚动到最终查询中。这样写意味着你相信CTE是以某种方式被处理并缓存在内存中的。那不是真的——请看另一个这样的问题。要进一步了解SQL Server的CTE实现,请访问。

优化器可以按任何有效顺序评估CTE。(就像where子句中的条件一样)优化器可以按照任何有效的顺序计算cte。(就像where条款中的条件一样)
CASE WHEN TotalVal = 0 THEN 0 ELSE Val / TotalVal END