Sql server SQL Server 2008 R2设备的零缺陷
请告诉我,如果我错过了什么,如果我正在失去理智 下面的查询生成一个Device by zero错误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
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