是否可以在应用 WHERE 子句之前执行 SQL 查询的 SELECT 子句中的计算?我的目标是 SQL Server 2008 R2,但我对一般感兴趣。我认为 SQL 标准涵盖了这一点。
取下表并查询:
CREATE TABLE TestTable
(
ID bigint primary key,
Accessed bigint null,
Created bigint null,
Modified bigint null
)
--insert the data here
SELECT ID, dateadd(ms, (Created % 864000000000) / 10000, dateadd(day, (Created / 864000000000) - 55517, '17530101')) AS EventTime, 3 AS EventType
FROM TestTable
WHERE (Created IS NOT NULL)
AND (Created <> 0)
AND (Created <= 2650467743999999999)
WHERE 谓词旨在过滤掉通过 SELECT 子句中的嵌套 dateadd() 调用传递时会导致日期时间溢出的值。在某些情况下,即使我确信计算会在满足 WHERE 谓词的每个值上成功,我仍然会看到溢出发生。在每种失败情况下,源数据中始终存在一些零值。
我的猜测是,查询规划器有时决定在应用过滤器之前进行计算,因此允许使用零值,从而导致溢出。我无法确认这一点,因为溢出发生时我看不到执行计划。
我的理论可靠吗?有办法确认吗?我对证实这个理论更感兴趣。如果我的理论是正确的,那么我就知道如何解决问题。
最佳答案
唉,您无法控制过滤何时发生。 SQL Server 认为将 SELECT
计算移至实际执行计划中的 WHERE
过滤之前对您有好处。您不需要这样的优惠,因为它会导致错误。
有一个修复方法,即使用 case
语句:
SELECT ID,
(case when Created <> 0 and Created < 2650467743999999999
then dateadd(ms, (Created % 864000000000) / 10000, dateadd(day, (Created / 864000000000) - 55517, '17530101'))
end) AS EventTime, 3 AS EventType
FROM TestTable
WHERE (Created IS NOT NULL) AND (Created <> 0) AND (Created <= 2650467743999999999);
如果您不喜欢重复条件,可以将其放入子查询中并测试 NULL
:
SELECT *
FROM (SELECT ID,
(case when Created <> 0 and Created < 2650467743999999999
then dateadd(ms, (Created % 864000000000) / 10000, dateadd(day, (Created / 864000000000) - 55517, '17530101'))
end) AS EventTime, 3 AS EventType
FROM TestTable
) tt
WHERE EventTime is not null;
case
语句保证评估 then
之前的 when
子句,尽管在上下文中使用它时有一些特殊性聚合的。
关于sql - SELECT 子句中的计算可以在应用 WHERE 谓词之前执行吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22046828/