Sql server Case语句中的sqlserver函数
SQL Server是否足够聪明,可以在case语句中对Sql server Case语句中的sqlserver函数,sql-server,Sql Server,SQL Server是否足够聪明,可以在case语句中对datediff函数调用求值一次,然后对每个when子句使用该值?或者函数被调用了“n”次,其中“n”是when子句的数量?很难看出SQL Server如何计算一次调用。该调用有一列作为参数,因此必须对每一行进行求值 因此,您的条件最好写为: select top 10 *, case when datediff(day,DateOfSale, getDate()) > 5 then '5'
datediff
函数调用求值一次,然后对每个when
子句使用该值?或者函数被调用了“n”次,其中“n”是when
子句的数量?很难看出SQL Server如何计算一次调用。该调用有一列作为参数,因此必须对每一行进行求值
因此,您的条件最好写为:
select top 10 *, case
when datediff(day,DateOfSale, getDate()) > 5 then '5'
when datediff(day,DateOfSale, getDate()) > 10 then '10'
... (more datediff clauses)
...
...
else '20'
end as jack
from Foo
虽然此查询不会:
select * from YourTable where dt < dateadd(day, -5, getdate())
很难看出SQL Server如何对调用进行一次评估。该调用有一列作为参数,因此必须对每一行进行求值 因此,您的条件最好写为:
select top 10 *, case
when datediff(day,DateOfSale, getDate()) > 5 then '5'
when datediff(day,DateOfSale, getDate()) > 10 then '10'
... (more datediff clauses)
...
...
else '20'
end as jack
from Foo
虽然此查询不会:
select * from YourTable where dt < dateadd(day, -5, getdate())
当然,但不是在您的情况下(表达式基于表列值,每行都会更改),但在任何情况下,都不要对表列值执行datediff,对谓词(比较)值运行dateadd,这样您的查询仍然可以使用DateOfSale上的任何现有索引
select * from YourTable where datediff(day, DateOfSale, getDate()) > 5
选择前10名*,
当DateOfSale
当然可以,但不是在您的情况下(表达式基于表列值,每行都会更改),但在任何情况下,都不要对表列值执行datediff,对谓词(比较)值运行dateadd,以便您的查询仍然可以使用DateOfSale上的任何现有索引
select * from YourTable where datediff(day, DateOfSale, getDate()) > 5
选择前10名*,
当DateOfSale
令人费解的是,这么多的答案都提到了索引。实际上,<代码> DATEDIF.<代码>不是sgabess,但在这里,当SQLServer中的查询优化器不考虑索引使用(除了试图找到覆盖的可扫描路径)时,这完全是不相关的。据我所知,涉及DATEDIFF的表达式作为索引路径的候选表达式与这个问题完全无关
很容易证明,一旦找到第一个真正的谓词,SQL Server确实会停止对CASE
语句中的谓词求值
为了证明这一事实,让我们编写一些示例数据:
select top 10 *,
case When DateOfSale < dateadd(day, -20, getDate()) then '20'
When DateOfSale < dateadd(day, -15, getDate()) then '15'
When DateOfSale < dateadd(day, -10, getDate()) then '10'
When DateOfSale < dateadd(day, -5, getDate()) then '5'
else '20' end jack
from Foo
请注意,如果我们曾经计算过1/0>1
,那么我们可能会遇到类似的“被零除的错误”。
。但是,对我的服务器运行此查询会产生十行,在Jack
列中都有“5”
如果我们去掉前10行,肯定会得到一些行,然后得到被零除的错误。因此,我们可以安全地得出结论,SQL Server正在对CASE语句进行早期退出评估
除此之外,它还告诉我们:
CASE语句按顺序计算其条件,并以满足条件的第一个条件停止
这个问题可能是想问,公共的DATEDIFF()
子表达式是否从所有CASE
语句中提升,计算一次,然后在每个谓词的上下文中进行计算。通过观察
上的SET SHOWPLAN_TEXT的输出,我认为我们可以得出结论,情况并非如此:
SELECT TOP 10 *, CASE
WHEN datediff(day,DateOfSale, getDate()) > 5 then '5'
WHEN datediff(day,DateOfSale, getDate()) > 10 then '10'
WHEN 1/0 > 1then 'boom'
ELSE '20' END
AS Jack
FROM Diffy;
由此,我们可以得出结论,这个查询的结构意味着对每一行和每一个谓词计算DATEDIFF()
,因此O(rows*predicates)
调用,最坏的情况是。这会给查询带来一些CPU负载,但是DATEDIFF()
并没有那么昂贵,不应该引起太大的关注。如果在实践中,它最终导致了性能问题,那么有一些方法可以从查询中手动提升计算。例如,DATEDIFF()。实际上,<代码> DATEDIF.<代码>不是sgabess,但在这里,当SQLServer中的查询优化器不考虑索引使用(除了试图找到覆盖的可扫描路径)时,这完全是不相关的。据我所知,涉及DATEDIFF的表达式作为索引路径的候选表达式与这个问题完全无关
很容易证明,一旦找到第一个真正的谓词,SQL Server确实会停止对CASE
语句中的谓词求值
为了证明这一事实,让我们编写一些示例数据:
select top 10 *,
case When DateOfSale < dateadd(day, -20, getDate()) then '20'
When DateOfSale < dateadd(day, -15, getDate()) then '15'
When DateOfSale < dateadd(day, -10, getDate()) then '10'
When DateOfSale < dateadd(day, -5, getDate()) then '5'
else '20' end jack
from Foo
请注意,如果我们曾经计算过1/0>1
,那么我们可能会遇到类似的“被零除的错误”。
。但是,对我的服务器运行此查询会产生十行,在Jack
列中都有“5”
如果我们去掉前10行,肯定会得到一些行,然后得到被零除的错误。因此,我们可以安全地得出结论,SQL Server正在对CASE语句进行早期退出评估
除此之外,它还告诉我们:
CASE语句按顺序计算其条件,并以满足条件的第一个条件停止
这个问题可能是想问,公共的DATEDIFF()
子表达式是否从所有CASE
语句中提升,计算一次,然后在每个谓词的上下文中进行计算。通过观察
上的SET SHOWPLAN_TEXT的输出,我认为我们可以得出结论,情况并非如此:
SELECT TOP 10 *, CASE
WHEN datediff(day,DateOfSale, getDate()) > 5 then '5'
WHEN datediff(day,DateOfSale, getDate()) > 10 then '10'
WHEN 1/0 > 1then 'boom'
ELSE '20' END
AS Jack
FROM Diffy;
由此,我们可以得出结论,该查询的结构意味着对每一行和每一行计算DATEDIFF()