8

如何使用 T-SQL 找到“一年中的第一个星期一”?

4

9 回答 9

11

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

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)

以上返回:

2012-01-02 00:00:00.000
于 2012-11-23T09:07:26.703 回答
3
    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
于 2012-11-23T09:42:41.120 回答
2

优雅不是;)

    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'
于 2012-11-23T09:14:34.470 回答
1

这是实现这一目标的一个示例:

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

于 2012-11-23T09:06:40.803 回答
1

试试这个:

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 演示

于 2012-11-23T09:21:13.067 回答
1

这种方法不使用像 1900 年这样的神奇年份或神奇日期。

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)

于 2017-08-08T08:57:03.167 回答
0

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

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 实际上可能是去年的日期,但是当您乘以周数时,一切都会解决。

于 2014-01-24T19:13:57.700 回答
0

我不确切知道为什么这里的答案很简单,真的很详细:

    // You can try any year
    DECLARE @YEAR INT = 2021
    // First you get the first day of the year
    DECLARE @FIRST_DAY_OF_YEAR DATE = CAST(@YEAR AS VARCHAR(4)) + '-01-01'
    // Then you get its weekday
    DECLARE @FIRST_DAY_OF_YEAR_WEEKDAY INT = DATEPART(WEEKDAY,@FIRST_DAY_OF_YEAR)
    // Then it's just a CASE matter, where you must see if the actual first day of the year is itself a monday or a sunday. If it's a monday we just return the first day, if it's a sunday we just add 1, if it's anything else beyond that we just have to substract the weekday from 9 (which is essentialy the second monday of the year). And we add the result to whichever day of the week is our first day of the year and we always get our first monday
    DECLARE @FIRST_MONDAY_OF_YEAR DATE =
    CASE
        WHEN @FIRST_DAY_OF_YEAR_WEEKDAY = 2 THEN @FIRST_DAY_OF_YEAR
        WHEN @FIRST_DAY_OF_YEAR_WEEKDAY = 1 THEN DATEADD(DAY, 1, @FIRST_DAY_OF_YEAR)
        ELSE DATEADD(DAY, 9 - @FIRST_DAY_OF_YEAR_WEEKDAY, @FIRST_DAY_OF_YEAR)
    END

    SELECT @FIRST_MONDAY_OF_YEAR
于 2021-08-17T10:20:29.853 回答
-1

我知道这是一个 8 年前的问题,但我想我还是会把帽子扔进戒指

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

--===== 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
;
于 2020-11-29T05:58:37.863 回答