获取“一天中的第几周”?
Posted
技术标签:
【中文标题】获取“一天中的第几周”?【英文标题】:Get 'number week of the day'? 【发布时间】:2020-09-18 02:48:59 【问题描述】:我有一个类似“2020-09-17”的日期,我想要这个:“第三个星期二 - 2020-09-17”,其中“第三个”表示 17/09 是从 9 月开始的第三个星期二。
有什么想法可以使用 SQL Server 解决这个问题吗?
【问题讨论】:
查看 sql server 提供的日期函数并试一试。 【参考方案1】:我刚才拼凑了这个功能。 仅在SET DATEFIRST 1
时有效。修改此函数以使用星期一不是一周的第一天的日历是读者的练习(注意:doing so is non-trivial)。
SET DATEFIRST 1; -- Set Monday as the first day-of-week.
CREATE FUNCTION dbo.GetDayOfWeekInMonth( @date date )
RETURNS int
AS
BEGIN
--SET DATEFIRST 1; -- can't use this inside a function
DECLARE @dayOfMonth int = DATEPART( day , @date );
DECLARE @dayOfWeek int = DATEPART( weekday, @date );
DECLARE @startOfMonth date = DATEFROMPARTS( YEAR( @date ), MONTH( @date ), 1 );
DECLARE @startOfMonthDayOfWeek int = DATEPART( weekday, @startOfMonth );
DECLARE @weekNumber int = @dayOfMonth / 7;
DECLARE @dayOfWeekInMonth int = CASE WHEN @startOfMonthDayOfWeek > @dayOfWeek THEN @weekNumber ELSE ( @weekNumber + 1 ) END;
RETURN @dayOfWeekInMonth
END
示例:
所以运行这个:
SET DATEFIRST 1
DECLARE @t TABLE ( Dt date NOT NULL, DoW int NOT NULL, DoWName nvarchar(20) NOT NULL, DoWoM int NOT NULL );
DECLARE @d int = 1
WHILE @d <= 30
BEGIN
DECLARE @dt date = DATEFROMPARTS( 2020, 9, @d );
INSERT INTO @t ( Dt, DoW, DoWName, DoWoM )
VALUES (
@dt,
DATEPART( weekday, @dt ),
DATENAME( weekday, @dt ),
dbo.GetDayOfWeekInMonth( @dt )
);
SET @d = @d + 1
END;
SELECT
*,
CASE DoWoM
WHEN 1 THEN CONCAT( 'First ' , DoWName, ' of ', DATENAME( month, Dt ) )
WHEN 2 THEN CONCAT( 'Second ', DoWName, ' of ', DATENAME( month, Dt ) )
WHEN 3 THEN CONCAT( 'Third ' , DoWName, ' of ', DATENAME( month, Dt ) )
WHEN 4 THEN CONCAT( 'Fourth ', DoWName, ' of ', DATENAME( month, Dt ) )
WHEN 5 THEN CONCAT( 'Fifth ' , DoWName, ' of ', DATENAME( month, Dt ) ) ELSE NULL
END AS [Text]
FROM
@t;
给我这个输出:
Dt DoW DoWName DoWoM Text
2020-09-01 2 Tuesday 1 First Tuesday of September
2020-09-02 3 Wednesday 1 First Wednesday of September
2020-09-03 4 Thursday 1 First Thursday of September
2020-09-04 5 Friday 1 First Friday of September
2020-09-05 6 Saturday 1 First Saturday of September
2020-09-06 7 Sunday 1 First Sunday of September
2020-09-07 1 Monday 1 First Monday of September
2020-09-08 2 Tuesday 2 Second Tuesday of September
2020-09-09 3 Wednesday 2 Second Wednesday of September
2020-09-10 4 Thursday 2 Second Thursday of September
2020-09-11 5 Friday 2 Second Friday of September
2020-09-12 6 Saturday 2 Second Saturday of September
2020-09-13 7 Sunday 2 Second Sunday of September
2020-09-14 1 Monday 2 Second Monday of September
2020-09-15 2 Tuesday 3 Third Tuesday of September
2020-09-16 3 Wednesday 3 Third Wednesday of September
2020-09-17 4 Thursday 3 Third Thursday of September
2020-09-18 5 Friday 3 Third Friday of September
2020-09-19 6 Saturday 3 Third Saturday of September
2020-09-20 7 Sunday 3 Third Sunday of September
2020-09-21 1 Monday 3 Third Monday of September
2020-09-22 2 Tuesday 4 Fourth Tuesday of September
2020-09-23 3 Wednesday 4 Fourth Wednesday of September
2020-09-24 4 Thursday 4 Fourth Thursday of September
2020-09-25 5 Friday 4 Fourth Friday of September
2020-09-26 6 Saturday 4 Fourth Saturday of September
2020-09-27 7 Sunday 4 Fourth Sunday of September
2020-09-28 1 Monday 4 Fourth Monday of September
2020-09-29 2 Tuesday 5 Fifth Tuesday of September
2020-09-30 3 Wednesday 5 Fifth Wednesday of September
【讨论】:
您的代码对我帮助很大,谢谢,我还将 SET 命令更改为 (DATEPART(dw, GETDATE()) + @@DATEFIRST + 6 - @WeekStartDay) % 7 + 1 作为评论您分享的链接【参考方案2】:我不得不更改下面这段代码的实现,因为当 thar 按预期返回 1 而不是 2 时,以前的解决方案不适用于某些日期,例如 2020-07-13。当然我需要一些“调整手”,但有一段时间我用来填充日历表。
create function dbo.getdayofweekinmonth( @date date )
returns int
as
begin
declare @dayofweek int = (datepart(dw, @date) + @@datefirst + 6 - 1) % 7 + 1;
declare @startofmonth date = datefromparts( year( @date ), month( @date ), 1 );
declare @month_days as table (d int) -- d as day number
while @startofmonth <= @date
begin
insert into @month_days values ((datepart(dw, @startofmonth) + @@datefirst + 6 - 1) % 7 + 1);
select @startofmonth = dateadd(day, 1, @startofmonth);
end
return (select count(*) from @month_days where d = @dayofweek)
end
【讨论】:
【参考方案3】:为了获得更高的性能,最好使用日期维度表并将其与您自己的表连接(日期维度是一个每天有一条记录的表,包含您需要的关于某个日期的所有信息)
【讨论】:
以上是关于获取“一天中的第几周”?的主要内容,如果未能解决你的问题,请参考以下文章