我正在调整 SQL Server 2012 中的查询,该查询由于DATENAME()
在列上使用函数检查数据是周末还是工作日时基数估计不正确而溢出到 tempdb。由于使用了该函数,该查询是 non-sargable 并且错误估计了行数(估计为 1700,实际为 38000)。
where 子句很简单:
WHERE DATENAME(WEEKDAY, vqc.DateRecorded) NOT IN ('Saturday', 'Sunday')
我希望使用持久计算列,然后对其进行索引:
ALTER TABLE <table_name> ADD IsWeekend AS DATENAME(WeekDay, DateRecorded) PERSISTED;
但是得到错误:
无法保留表中的计算列“IsWeekend”,因为该列是不确定的。
根据BOL,大量的 Date 函数不能持久化,因为它们是不确定的。
这是因为结果取决于服务器会话的 LANGUAGE 和 DATEFORMAT 设置。例如,表达式 CONVERT (datetime, '30 listopad 1996', 113) 的结果取决于 LANGUAGE 设置,因为字符串 '30 listopad 1996' 表示不同语言中的不同月份。同样,在表达式 DATEADD(mm,3,'2000-12-01') 中,数据库引擎根据 DATEFORMAT 设置解释字符串 '2000-12-01'。
使用发布在Stack OverflowMONTH()
上的语句来解决此问题的函数有一种有趣的方法,但这不适用于由于和设置。CASE
DATENAME
SET DATEFIRST
LANGUAGE
除了在我的查询中加入日历表然后从那里过滤周末之外,还有没有办法确定日期是否是周末,以便可以将其保留然后编制索引?
还是我试图使情况过于复杂?