Bor*_*ich 13
t-clausen.dk的答案确实有效,但可能并不清楚它为何起作用(既不对你也不对你后面的开发人员).由于增加的清晰度有时会以简洁和性能为代价,我想解释一下为什么它可以用来防止你更喜欢使用那种更短的语法.
SELECT t.*
FROM <table> t CROSS JOIN
(SELECT DATEDIFF(day, 0, getdate() - DATEDIFF(day, 0, getdate()) %7) lastmonday) a
WHERE t.yourdate >= a.lastmonday - 7 and yourdate < a.lastmonday
Run Code Online (Sandbox Code Playgroud)
datetime
内部存储SQL Server存储datetime
为两个4字节整数; 前四个字节表示自19/1年1月1日以来(或者在1/1/1900之前,对于负数)的天数,后四个字节表示自午夜以来的毫秒数.
datetime
带int
或decimal
因为datetime
存储为两个4字节整数,所以很容易在T-SQL中的数字和日期数据类型之间移动.例如,SELECT GETDATE() + 1
返回相同SELECT DATEADD(day, 1, GETDATE())
,并且CAST(40777.44281 AS datetime)
相同2011-08-24 10:37:38.783
.
由于datetime的第一个整数部分,如上所述,自19/1年1月1日以来的天数(也称为SQL Server Epoch),CAST(0 as datetime)
根据定义相当于
1900-01-01 00:00:00
在这里,事情开始变得既棘手又有趣.首先,我们已经建立了,当0
一个日期被处理,这是一样的1/1/1900,所以DATEDIFF(day, '1/1/1900', GETDATE())
是一样的DATEDIFF(day, 0, GETDATE())
-既会因为1/1/1900返回天的当前数量.但是,等一下:当前的天数恰好是datetime的前四个字节所代表的!在一个语句中我们做了两件事:1)我们删除了返回的"时间"部分GETDATE()
,我们得到了一个整数值,我们可以用它来计算查找最近的星期日和上周一的一点点更轻松.
DATEDIFF(day, 0, GETDATE()) % 7
利用了DATEPART(day, 0)
(过分强调要点的风险DATEPART(day, '1/1/1900')
)返回2
(星期一)这一事实.1 因此,DATEDIFF(day, 0, GETDATE()) % 7
将始终生成当前日期从星期一起的天数.
1 除非您使用了更改了默认行为DATEFIRST
.
这对于它自己的标题来说几乎是微不足道的,但是在这一点上我们可以将迄今为止所有的东西放在一起:
GETDATE() - DATEDIFF(day, 0, GETDATE()) %7
给你最近的星期一DATEDIFF(day, 0, GETDATE() - DATEDIFF(day, 0, GETDATE()) %7)
给你最近的星期一作为整个日期,没有时间部分.取代使用BETWEEN运算符(包括在内),发布的答案排除在最后一天,因此无需进行任何转换或计算以获得正确的日期范围:
t.yourdate >= a.lastmonday - 7
从最近的第二个星期一的午夜(或包括)返回日期的记录t.yourdate < a.lastmonday
返回最近一个星期一午夜之前(但不包括)午夜的记录.我非常支持编写易于理解的代码,无论是对于您还是一年后跟随您的开发人员(可能也是您).我相信我之前发布的答案对于新手T-SQL程序员来说应该是可以理解的.但是,t-clausen.dk的答案很简洁,表现良好,可能会在生产代码中遇到,所以我想给出一些解释,以帮助未来的访问者了解它的工作原理.