【问题标题】:SQL Server - Finding the first day of the weekSQL Server - 查找一周的第一天
【发布时间】:2013-05-14 16:45:53
【问题描述】:

我一直在寻找一大段代码来找到本周的第一天,我到处都看到了这个:

DATEADD(WK, DATEDIFF(WK,0,GETDATE()),0)

每个地方都说这是我要找的代码。

这段代码的问题在于,如果你在星期日运行它,它会选择下一个星期一。


如果我跑:

SELECT GetDate() , DATEADD(WK, DATEDIFF(WK,0,GETDATE()),0)

今天(星期二)的结果:

2013-05-14 09:36:39.650................2013-05-13 00:00:00.000

这是正确的,它选择了 13 号星期一。


如果我跑:

SELECT GetDate()-1 , DATEADD(WK, DATEDIFF(WK,0,GETDATE()-1),0)

昨天(星期一)的成绩:

2013-05-13 09:38:57.950................2013-05-13 00:00:00.000

这是正确的,它选择了 13 号星期一。


如果我跑:

SELECT GetDate()-2 , DATEADD(WK, DATEDIFF(WK,0,GETDATE()-2),0)

12日(周日)成绩:

2013-05-12 09:40:14.817................2013-05-13 00:00:00.000

这是不正确的,它选择了13号星期一,而应该选择上一个星期一,6号。

谁能告诉我这里发生了什么?我很难相信没有人指出这不起作用,所以我想知道我错过了什么。

【问题讨论】:

  • 我认为问题的根源在于使用日期 0,在 SQL Server 中它解析为 '1900-01-01' - 这是星期一。
  • @Pondlife:不是这样。问题是为什么返回不同的星期一取决于日期是星期天还是一周中的任何其他日子。

标签: sql-server tsql sql-server-2012


【解决方案1】:

DATEDIFF 返回“不正确”的周差,最终导致错误的星期一。那是因为 DATEDIFF(WEEK, ...) 不尊重 DATEFIRST 设置,我假设您已将其设置为 1(星期一),而是始终认为一周交叉是从星期六到星期日,或者换句话说,在这种情况下,它无条件将星期日视为一周的第一天。

至于那个的解释,到目前为止我还没有找到官方的解释,但我相信这一定与DATEDIFF函数是其中之一有关SQL Server 将其视为always deterministic。显然,如果DATEDIFF(WEEK, ...) 依赖于DATEFIRST,它就不再被认为是总是确定性的,我只能猜测这不是 SQL Server 的开发人员想要的。

要找到一周的第一天,我会(而且实际上经常这样做)使用@Jasmina Shevchenko's answer 中的第一个建议:

DATEADD(DAY, 1 - DATEPART(WEEKDAY, @Date), @Date)

DATEPART 确实尊重DATEFIRST 设置,并且(很可能因此)它不在始终确定函数列表中。

【讨论】:

    【解决方案2】:

    试试这个 -

    SET DATEFIRST 1
    
    DECLARE @Date DATETIME
    SELECT @Date = GETDATE()
    
    SELECT CAST(DATEADD(DAY, 1 - DATEPART(WEEKDAY, @Date), @Date) AS DATE)
    
    SELECT CAST(@Date - 2 AS DATE), CAST(DATEADD(WK, DATEDIFF(WK, 0, @Date-2), 0) AS DATE)
    

    结果:

    ---------- ----------
    2013-05-12 2013-05-13
    

    【讨论】:

      【解决方案3】:

      SQL Server 有一个SET DATEFIRST 函数,它允许你告诉它一周的第一天应该是什么。 SET DATEFIRST = 1 告诉它将星期一视为一周的第一天。您应该通过@@DATEFIRST 检查服务器的默认设置。或者您可以在查询开始时简单地更改它。

      一些参考资料:

      MSDN

      Similar Question

      【讨论】:

      • DATEDIFF(WEEK) 忽略 DATEFIRST 设置,这就是为什么会为星期日日期返回错误的星期一(当 @@DATEFIRST = 1 时)。
      【解决方案4】:

      这对我来说就像一个魅力:

      将星期一设置为一周的第一天而不更改 DATEFIRST 变量:

      -- FirstDayWeek    
      select dateadd(dd,(datepart(dw, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) * -1) + 2, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) as FirstDayWeek;
      
      -- LastDayWeek
      select dateadd(dd, (case datepart(dw, [yourDate]) when 1 then datepart(dw, dateadd(dd,-1,[yourDate])) else datepart(dw, [yourDate]) end * -1) + 8, case datepart(dw, [yourDate]) when 1 then dateadd(dd,-1,[yourDate]) else [yourDate] end) as LastDayWeek;
      

      将星期日设置为一周的第一天而不更改 DATEFIRST 变量

      select convert(varchar(50), dateadd(dd, (datepart(dw, [yourDate]) * -1) + 2, [yourDate]), 103) as FirstDayWeek, convert(varchar(50), dateadd(dd, (datepart(dw, [yourDate]) * -1) + 8, [yourDate]), 103) as LastDayWeek;
      

      您可以通过 GETDATE() 更改 [yourDate] 以进行测试

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-02
        • 2021-03-11
        • 1970-01-01
        • 2017-12-29
        • 1970-01-01
        • 2020-06-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多