始终返回上周一至周日的数据

Kal*_*Kal 4 t-sql

如何编写一个始终从上周一到最后一个周日返回数据的sql语句?任何指导表示赞赏.

谢谢.

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)

SQL Server如何在datetime内部存储

SQL Server存储datetime为两个4字节整数; 前四个字节表示自19/1年1月1日以来(或者在1/1/1900之前,对于负数)的天数,后四个字节表示自午夜以来的毫秒数.

使用datetimeintdecimal

因为datetime存储为两个4字节整数,所以很容易在T-SQL中的数字和日期数据类型之间移动.例如,SELECT GETDATE() + 1返回相同SELECT DATEADD(day, 1, GETDATE()),并且CAST(40777.44281 AS datetime)相同2011-08-24 10:37:38.783.

1/1/1900

由于datetime的第一个整数部分,如上所述,自19/1年1月1日以来的天数(也称为SQL Server Epoch),CAST(0 as datetime)根据定义相当于 1900-01-01 00:00:00

DATEDIFF(day,0,GETDATE())

在这里,事情开始变得既棘手又有趣.首先,我们已经建立了,当0一个日期被处理,这是一样的1/1/1900,所以DATEDIFF(day, '1/1/1900', GETDATE())是一样的DATEDIFF(day, 0, GETDATE())-既会因为1/1/1900返回天的当前数量.但是,等一下:当前的天数恰好是datetime的前四个字节所代表的!在一个语句中我们做了两件事:1)我们删除了返回的"时间"部分GETDATE(),我们得到了一个整数值,我们可以用它来计算查找最近的星期日和上周一的一点点更轻松.

星期一的Modulo 7

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的答案很简洁,表现良好,可能会在生产代码中遇到,所以我想给出一些解释,以帮助未来的访问者了解它的工作原理.