使用以下SQL表(在此处小提琴:http://sqlfiddle.com/#!3/578bc/1/0):
CREATE TABLE [dbo].[tbl_DateExample] (
[ID] [INT] IDENTITY(1, 1) NOT NULL ,
[BookingDate] [DATE] NOT NULL ,
[WeekEnding] AS ( DATEADD(DAY, ( 6 ) - ( ( DATEPART(WEEKDAY, [BookingDate]) + @@datefirst ) - ( 2 ) ) % ( 7 ), [BookingDate]) ) ,
CONSTRAINT [PK_tbl_DateExample] PRIMARY KEY CLUSTERED ( [ID] ASC )
)
请注意它使用计算列,此计算列计算BookingDate列中任何日期的WeekEnding(星期日)日期,而不管@@datefirst
环境变量 - 此列必须仅包含星期日。
这在生产中效果很好,但我们需要对此计算列应用索引,为此我们需要将其作为持久计算列,遗憾的是我们使用@@datefirst
使其成为非确定性的防止持久性和索引。
我们如何重新创建此列数据(即,在BookingDate列中的任何日期的WeekEnding(星期日)),但使其成为确定性的&准备索引?
PS:我宁愿避免使用触发器,因为生产表已经是一个极其复杂的高流量表,其中包含数百万行&已有几个触发器。
编辑:使用的最终代码:
DATEADD(DAY, 6 - DATEDIFF(DAY, CONVERT(DATE, '01/01/1990', 103), BookingDate) % 7, BookingDate)
答案 0 :(得分:2)
一种丑陋但可靠的解决方案是,依赖于固定的日期值,然后使用模7的日期差作为DATEPART
函数的替代:
DATEPART(WEEKDAY, [BookingDate]) -- with @@datefirst = 1
相当于:
DATEDIFF(DAY, CONVERT(DATETIME,'1990-01-01',120), [BookingDate]) % 7 + 1 -- because 1990-01-01 is a monday
所以请使用以下内容。 注意:我还没有对此进行过测试,所以你应该在[WeekEnding]
计算中调整偏移值,直到你做对了:
CREATE TABLE [dbo].[tbl_DateExample] (
[ID] [INT] IDENTITY(1, 1) NOT NULL ,
[BookingDate] [DATE] NOT NULL ,
[WeekEnding] AS ( DATEADD(DAY, ( 6 ) - (DATEDIFF(DAY, CONVERT(DATETIME,'1990-01-01 00:00:00.000',120), [BookingDate]) % 7), [BookingDate]) ) ,
CONSTRAINT [PK_tbl_DateExample] PRIMARY KEY CLUSTERED ( [ID] ASC )
)
此外,如果您在1990-01-01之前有BookingDate
个值,则可能会遇到DATEDIFF返回负值的问题。在这种情况下,请调整固定日期值,以确保它位于任何BookingDate
值之前。