我有一个类似'2020-09-17'的日期,我想要这样:'Third Tuesday-2020-09-17',其中“ Third”代表17/09是9月的第三个星期二。
是否有使用SQL Server解决此问题的想法?
答案 0 :(得分: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
答案 1 :(得分:0)
我不得不在下面更改此代码的实现,因为以前的解决方案不适用于某些日期,例如2020-07-13,此时thar返回1而不是预期的2。当然,在那儿我需要一些“调教之手”,但有一段时间我正在使用它来填充日历表。
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
答案 2 :(得分:0)
为获得更高的性能,最好使用“日期维度表”并将其与您自己的表联接(“日期维度”表每天都有一条记录,并且包含您需要的有关特定日期的所有信息)