![](/img/trans.png)
[英]T-SQL calculate the first monday of the first ISO week in a year and enumerate all weeks as from-to periods
[英]First Monday of the Year in SQL Server
如何使用 T-SQL 找到“一年中的第一个星期一”?
这是 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
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
优雅不是;)
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'
这是实现这一目标的一个示例:
http://sqlbump.blogspot.nl/2010/01/first-monday-of-year.html
试试这个:
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
这种方法不使用像 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)
我需要按周对一些数据进行分组并显示每周的第一天(在我的情况下是星期日)。 我使用以下内容来计算一年的第一个星期日,然后您可以使用周数来获取给定日期发生的一周的开始。
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 实际上可能是去年的日期,但是当您乘以周数时,一切都会解决。
我知道这是一个 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
;
我不知道为什么这里的答案非常简单,真的:
// 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
-- for specific date
DECLARE @date DATETIME = '20220909'
SELECT CAST(DATEADD(WEEK, - (DATEPART(DAYOFYEAR, @date) / 7) + 1, @date - (DATEPART(WEEKDAY, @date) - 2)) AS DATE);
-- for current date
SELECT CAST(DATEADD(WEEK, - (DATEPART(DAYOFYEAR, GETDATE()) / 7) + 1, GETDATE() - (DATEPART(WEEKDAY, GETDATE()) - 2)) AS DATE);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.