SQL Server年度的第一个星期一

First Monday of the Year in SQL Server

如何使用T-SQL查找"一年中的第一个星期一"?


以下是ngruson发布的链接中的示例(http://sqlbump.blogspot.nl/2010/01/first-monday-of-year.html):

1
2
3
4
5
6
7
DECLARE @DATE datetime
DECLARE @YEAR INT = 2012

SET @DATE = DATEADD(YEAR, @YEAR - 1900, 0)

SELECT DATEADD(DAY, (@@DATEFIRST - DATEPART(WEEKDAY, @DATE) +
    (8 - @@DATEFIRST) * 2) % 7, @DATE)

以上返回:

1
2012-01-02 00:00:00.000

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    Here,
    1) DATEPART FUNCTION FOR finding DAY OF week.
Here 1=sunday,2=monday,..,7=saturday.
    2) FIRST find OUT IS 2(monday) IN CASE WHEN
 condition THEN GET same DATE,
    3) IF IS sunday(1) THEN ADD 1 DAY AND GET NEXT
 DAY DATE IS FOR monday,
    4) IF IS NOT 2(monday) AND greater THEN 2 THEN find
difference BETWEEN lastday(7) AND ADD 2 days ,
 so we reach TO monday DATE.

    Here are you CHANGE YEAR IN @YEAR variable. Ex:

        DECLARE @DATE datetime
        DECLARE @YEAR INT = 2012

        SET @DATE= CONVERT(VARCHAR(4),@YEAR) + '-01-01'
        SELECT @DATE,(CASE WHEN DATEPART(DW,@DATE)=2 THEN @DATE
                     WHEN DATEPART(DW,@DATE)=1 THEN DATEADD(DAY,1,@DATE)
                     ELSE DATEADD(DAY,7-DATEPART(DW,@DATE)+2,@DATE)
                      END) AS MondayDateis

这不是优雅的;)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    DECLARE @YEAR DATETIME = '01 jan 2012'

    SELECT [DAY]
    FROM
        (
            SELECT @YEAR [DAY] UNION ALL
            SELECT DATEADD(DAY, 1, @YEAR) UNION ALL
            SELECT DATEADD(DAY, 2, @YEAR) UNION ALL
            SELECT DATEADD(DAY, 3, @YEAR) UNION ALL
            SELECT DATEADD(DAY, 4, @YEAR) UNION ALL
            SELECT DATEADD(DAY, 5, @YEAR) UNION ALL
            SELECT DATEADD(DAY, 6, @YEAR)
        ) x
    WHERE
        DATENAME(DW, [DAY]) = 'Monday'


此方法不使用像1900或魔术日期这样的魔术年份。

1
2
3
4
5
6
7
DECLARE @first_year_day     DATE,
        @first_year_monday  DATE,
        @YEAR               INT = 2017

SET @first_year_day    = CAST('1/1/' + str(@YEAR, 4) AS DATE)
SET @first_year_monday    = DATEADD(DAY, (9 - DATEPART(dw, @first_year_day)) % 7, @first_year_day)
SELECT @first_year_monday

该代码仅在SQL Server首选项中将周配置为以星期日开始时才有效。对于大多数英语安装,这是默认设置(在这种情况下,SELECT @@ DATEFIRST将返回7)。


尝试:

1
2
3
4
DECLARE @yr INT=2020
SELECT CASE WHEN datepart(weekday,dateadd(YEAR,@yr-1900,0))=1 THEN dateadd(YEAR,@yr-1900,1)
       ELSE dateadd(dd,8-(datepart(weekday,dateadd(YEAR,@yr-1900,0))),dateadd(YEAR,@yr-1900,1))
END

SQL Fiddle演示


这是一个完成此任务的示例:

http://sqlbump.blogspot.nl/2010/01/first-monday-of-year.html


我知道这是一个8岁的问题,但以为我还是会把帽子扔进戒指

下面的第一个代码段创建了一个测试表,以证明后面的代码不会遇到任何RBAR问题。解决方案实际上是在第二个片段的结果中填充" FirstMondayOfYear"列的相当简短的公式。其他所有内容都只是添加到演示中。不需要单独的SET,不需要CASE语句和对DATEFIRST的引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--===== Create a test table that contains random dates and times from 1900-01-01 up to and not
     -- including 2100-01-01.
   DROP TABLE IF EXISTS #MyHead
;
 SELECT TOP 100000
        SomeDateTime = RAND(CHECKSUM(NEWID()))*DATEDIFF(dd,'1900','2100')+CONVERT(DATETIME,'1900') --Inherently DATETIME
--        SomeDateTime = CONVERT(DATETIME2(7),RAND(CHECKSUM(NEWID()))*DATEDIFF(dd,'1900','2100')+CONVERT(DATETIME,'1900')) --DATETIME2()
--        SomeDateTime = CONVERT(DATE,ABS(CHECKSUM(NEWID())%DATEDIFF(dd,'1900','2100'))+CONVERT(DATETIME,'1900')) --DATE
   INTO #MyHead
   FROM      sys.all_columns ac1
  CROSS JOIN sys.all_columns ac2
;
--===== Return the first Monday for the year of each given date (and the original date) as well
     -- as a weekday name and day check for the date created by the formula.  The FirstMondayOfYear
     -- should (obviously) always be a Monday and it should always be a day of 7 or less.
   WITH cteFindMonday AS
(
 SELECT  SomeDateTime
        ,FirstMondayOfYear  = DATEADD(dd,(DATEDIFF(dd,'1753',DATENAME(yy,SomeDateTime))+6)/7*7,'1753')
   FROM #MyHead
)
 SELECT  SomeDateTime
        ,FirstMondayOfYear
        ,DoW     = DATENAME(dw,FirstMondayOfYear)
        ,IsValid =  IIF(    DATENAME(dw,FirstMondayOfYear) = 'Monday'
                        AND DATEPART(dd,FirstMondayOfYear) <= 7
                    ,1,0)
   FROM cteFindMonday
  ORDER BY SomeDateTime
;

我需要按周对一些数据进行分组,并显示每周的第一天(在我的情况下为星期日)。我使用以下代码来计算一年中的第一个星期日,然后您可以使用周数来获取给定日期发生在一周的开始。

1
2
3
4
5
6
7
8
9
10
DECLARE @firstSundayThisYear DATE,
    @jan1ThisYear DATE,
    @currentYear INT;

SELECT @jan1ThisYear = '01-jan-' + CAST(DATEPART(YEAR, GETDATE()) AS VARCHAR(4)),
    @currentYear = DATEPART(YEAR, GETDATE());

SET @firstSundayThisYear = DATEADD(DAY, -DATEPART(weekday, @jan1ThisYear) + 1, @jan1ThisYear);

PRINT @firstSundayThisYear

注意:@firstSundayThisYear实际上可能是去年的日期,但是当您乘以周数时,所有日期都可以计算出来。