SQL函数以格式“ YYYYWW”递增6个字符的ISO日期字段

如何解决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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?