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]

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...