如何解决SQL函数以格式“ YYYYWW”递增6个字符的ISO日期字段
我有几个表,这些表使用6个字符的年份和ISO周来存储每周数据,格式为'YYYYWW'。例如,2020年的第一周将是“ 202001”。我正在使用sql Server 2012(SP1)11.0.3156。
我正在尝试编写一个sql函数,该函数使我可以增加工作的周数,以便可以编写在时间上向前和向后查询的查询。所以我的函数将像这样工作:
PRINT dbo.increment_week ('202244',-2) would simply return/print ‘202242’
我希望函数将整数作为第二个参数,并将该周数向前移动+ ive,向后移动-ive。
足够简单,但并非所有年份都有52周。因此,我编写了函数来应对这一方面。但是其他ISO周问题使我的功能无法正常工作(或者至少我希望它如何工作)。我在欧洲运行此程序,不知道这是否会影响ISO在sql中的工作方式,还是问题所在。
我不知道该如何解决。有没有人对如何解决这个问题有任何想法?任何帮助表示赞赏,谢谢。这是sql代码和一些示例输出:
CREATE FUNCTION dbo.increment_week(@week_to_increment char(6),@increment_weeks int)
RETURNS char(6)
AS
BEGIN
DECLARE @year_start_date date,@current_week_date date,@new_date date
DECLARE @Week_Of_Year_Text char(2),@year_Text char(4)
DECLARE @week_of_first_of_Year int,@current_week_int int
SET @year_start_date = CAST(LEFT(@week_to_increment,4) + '0101' AS DATE)
SET @current_week_int = CAST(RIGHT(@week_to_increment,2) AS INT)
SET @week_of_first_of_Year = DATEPART(isoww,@year_start_date)
/* If start week is 53 move on one week */
SET @year_start_date = DATEADD(week,IIF(@week_of_first_of_Year = 53,1,0),@year_start_date)
SET @current_week_date = DATEADD(week,@current_week_int,@year_start_date)
SET @new_date = DATEADD(week,@increment_weeks,@current_week_date)
SET @week_Of_Year_Text = RIGHT('00'+ CAST(DATEPART(ISO_WEEK,@new_date) AS NVARCHAR(2)),2)
SET @year_Text = CONVERT(CHAR(4),DATEPART(YEAR,DATEADD(day,26 - DATEPART(isoww,@new_date),@new_date)))
RETURN @year_Text + @week_Of_Year_Text
END
GO
Here are some sample calls to the function:
PRINT dbo.increment_week ('202244',-2) /* correct returns '202242' */
PRINT dbo.increment_week ('202244',0) /* correct returns '202244' */
PRINT dbo.increment_week ('202244',2) /* correct returns '202246' */
PRINT dbo.increment_week ('202201',-2) /* correct returns '202251' */
PRINT dbo.increment_week ('202201',0) /* correct returns '202201' */
PRINT dbo.increment_week ('202201',2) /* correct returns '202201' */
PRINT dbo.increment_week ('202044',-2) /* wrong returns '202043' not '202042' */
PRINT dbo.increment_week ('202044',0) /* wrong returns '202045' not '202044' */
PRINT dbo.increment_week ('202044',2) /* wrong returns '202047' not '202046' */
PRINT dbo.increment_week ('202001',-2) /* wrong returns '201952' not '201951' */
PRINT dbo.increment_week ('202001',0) /* wrong returns '202002' not '202001' */
PRINT dbo.increment_week ('202001',2) /* wrong returns '202044' not '202003' */
从评论中得到一些启发,我添加了一个案例声明,该声明现在似乎很有效。可以简化一下,但是这里是:
CREATE FUNCTION dbo.increment_week(@week_to_increment char(6),@increment_weeks int)
RETURNS char(6)
AS
BEGIN
DECLARE @year_start_date date,4) + '0101' AS DATE)
SET @week_of_first_of_Year = DATEPART(isoww,@year_start_date)
/*===========works but code Could be simplified?=======*/
SET @year_start_date = CASE
WHEN DATEPART(dw,@year_start_date) = 1
THEN @year_start_date /* Sunday */
WHEN DATEPART(dw,@year_start_date) = 2
THEN DATEADD(day,IIF(@week_of_first_of_Year = 1,-1,6),@year_start_date) /* Monday */
WHEN DATEPART(dw,@year_start_date) = 3
THEN DATEADD(day,-2,5),@year_start_date) /* Tuesday */
WHEN DATEPART(dw,@year_start_date) = 4
THEN DATEADD(day,-3,4),@year_start_date) /* Wednesday */
WHEN DATEPART(dw,@year_start_date) = 5
THEN DATEADD(day,-4,3),@year_start_date) /* Thursday */
WHEN DATEPART(dw,@year_start_date) = 6
THEN DATEADD(day,-5,2),@year_start_date) /* Friday */
WHEN DATEPART(dw,@year_start_date) = 7
THEN DATEADD(day,-6,1),@year_start_date) /* Saturday */
ELSE @year_start_date
END
SET @year_start_date = DATEADD(week,@year_start_date) /* If start week is 53 move on one week */
SET @current_week_int = CAST(RIGHT(@week_to_increment,2) AS INT)
SET @current_week_date = DATEADD(week,@new_date)))
RETURN @year_Text + @week_Of_Year_Text
END
GO
解决方法
您可以尝试以下操作来增强一周的运动力:
CREATE FUNCTION dbo.increment_week(@week_to_increment int,@increment_weeks int)
RETURNS int
AS
BEGIN
DECLARE @RetVal int;
DECLARE @year INT = @week_to_increment/100
DECLARE @CW INT = @week_to_increment%100
SET @CW = @CW -1;
DECLARE @d DATE = CONVERT(DATE,CAST(@year * 10000 + 101 AS NVARCHAR(8)),112)
SET @d = DATEADD(DAY,@CW*7,DATEADD(d,DATEDIFF(d,'1900-01-6',@d)%7,@d))
DECLARE @MovedWeek DATE = DATEADD(DAY,@increment_weeks * 7,@d)
SET @RetVal = DATEPART(YEAR,@MovedWeek) * 100 + DATEPART(iso_week,@MovedWeek);
RETURN @RetVal;
END
GO
这个想法的简短描述:
- 您会在一年的1月1日到达
- 您将移至第一个星期日(或星期一-取决于您将星期日算作一周的第一天还是最后一天)
- 然后将您的第一个星期添加到该日期(-1,因为您已经处于第2步之后的第1周)
- 之后,您上下移动MoveWeeks中定义的周数
尝试使用波纹管功能。
CREATE FUNCTION [dbo].[increment_week] (@yyyyww CHAR(6),@increment_weeks INT)
RETURNS VARCHAR(6)
AS
BEGIN
DECLARE @StartDatetime DATE;
DECLARE @yyyy CHAR(4) = LEFT(@yyyyww,4);
DECLARE @ww TINYINT= RIGHT(@yyyyww,2);
SET @StartDatetime = CAST(@yyyy AS DATETIME) - DAY(CAST(@yyyy AS DATETIME)) + 1 + (@ww - 1) * 7;
SET @StartDatetime = DATEADD(WW,@increment_weeks,@StartDatetime);
RETURN CONCAT(DATEPART(YEAR,CONVERT(varchar(10),@StartDatetime,120)),RIGHT(CONCAT('00',DATEPART(WEEK,CONVERT(VARCHAR(10),120))),2))
END
GO
PRINT dbo.increment_week('202001',2)
--DROP FUNCTION [dbo].[increment_week]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。