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实际上可能是去年的日期,但是当您乘以周数时,所有日期都可以计算出来。