Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 与“CTE”关联的CTE查询;Where子句;在Where子句中的求值条件之前不执行_Sql Server_Tsql - Fatal编程技术网

Sql server 与“CTE”关联的CTE查询;Where子句;在Where子句中的求值条件之前不执行

Sql server 与“CTE”关联的CTE查询;Where子句;在Where子句中的求值条件之前不执行,sql-server,tsql,Sql Server,Tsql,在执行下面的查询时,我遇到了一个奇怪的行为 WITH X1 AS ( SELECT 1 AS N1, 0 AS N2 UNION ALL SELECT 1 AS N1, 1 AS N2 ) ,X2 AS ( SELECT * FROM X1 WHERE N2>0 ) SELECT N1,N2,N1/N2 FROM X2 输出: 然而,当我在上面的select语句中输入where条件时 SELECT N1,N2,N1/N2 FROM X2 WHERE N1/N2>0

在执行下面的查询时,我遇到了一个奇怪的行为

WITH X1 AS 
(
  SELECT 1 AS N1, 0 AS N2
  UNION ALL
  SELECT 1 AS N1, 1 AS N2
)
,X2 AS
(
 SELECT * FROM X1 WHERE N2>0
)
SELECT N1,N2,N1/N2 FROM X2
输出:

然而,当我在上面的select语句中输入where条件时

SELECT N1,N2,N1/N2 FROM X2
WHERE N1/N2>0
我遇到了“被零除的错误”。请任何人解释一下我为什么会这样做
获取此错误?

使用
行目标将强制优化器在评估
where

 WITH X1 AS 
    (
      SELECT 1 AS N1, 0 AS N2
      UNION ALL
      SELECT 1 AS N1, 1 AS N2
    )
    ,X2 AS
    (
     SELECT top 10 * FROM X1 WHERE N2>0
    )
    SELECT N1,N2,N1/N2,* FROM X2
    WHERE N1/N2>2

因为
1/0
是0的除法,结果集中有一行
N1
的值为
1
N2
为0:
N1/N2=1/0=ERROR
。Hi@Larnu,我正在从X2的结果中执行select,该结果返回一行N2>0。所以N1/N2是1/1,它不应该是零。这是因为优化器没有按照所写的顺序执行语句(也没有义务)。这是
CTE
s的一个错误概念,虽然它是作为一个自包含查询编写的,但它不是。您假设SQL Server只根据从
X2
返回的行对其进行计算。但情况并非如此,它可以在对行进行筛选之前推动这样的计算。使用duse
N1/NULLIF(N2,0)
而不是
N1/N2
,因此,根据
0
对其进行求值并不重要,它不会强制执行任何此类操作。在这种情况下,你很幸运,没有什么强迫你这么做。这不是一个强有力的解决方案,也许武力是用词不当。我已经多次讨论过这一点,认为这是一种让优化器评估中间结果的调整技巧,我想不起来是Arron Bertrand还是Grant Fritchey,但在我使用它的地方,它总是按预期工作。可能是这样的情况:在当前版本的产品中,SQL Server永远不会将计算标量的计算重新排序为低于
TOP
。我不知道,但除非这是一个有文档记录的特性,否则它总是会被更改,使用
NULLIF
CASE
将更加健壮,因为它不依赖(可能随时间变化)优化器的怪癖。我同意在这个用例中使用NULLIF处理是合适的,作为使用派生表的行目标的示例,如果存在重新排序操作中断的内在原因,我将更有信心使用它。对于连接的结果,显然需要计算连接的行,这样优化器就很难重新排序。在放置计算标量的情况下,它不会影响放置在平面中计算表达式
N1/N2
的行数-这只会影响进入
TOP
的列数,而不会影响行数,因此完全有可能在将来对其重新排序