SQL 服务器的 Epi-week query/method

Epi-week query/method for SQL Server

epi周的定义如下:

"The first epi week of the year ends, by definition, on the first Saturday of January, as long as it falls at least four days into the month. Each epi week begins on a Sunday and ends on a Saturday."

参考:1

我用服务器语言 (C#/Java) 实现了它们,但我的问题是 return 来自 SQL 服务器存储过程的 epi 周和 epi 年

我强烈建议您在数据库中创建 Calendar table(如果您还没有的话)。

它是一个 table 每一天都有一行的时间足以满足您的需求。

向 table 添加一列 EpiWeek 并填充一次。然后在任何需要的地方使用它,而不是即时计算它。

日历 table 在许多领域都很有用,并有助于使用 SQL 基于集合的查询解决各种问题。 Calendar table 是 Numbers table 的特例,也经常有用。

详细示例见:

Why should I consider using an auxiliary calendar table?

本文有一节是关于 ISO 周数的。我不确定 ISO Week 和 Epi Week 是否相同,但您可以查看 Aaron Bertrand 如何计算 ISO 周数的示例:

Many, many, many people are dissatisfied with the way SQL Server calculates week number. Its strange algorithm used in DATEPART(WEEK, <date>) does not always yield the same number as the ISO standard, which dictates that week 1 is the first week with 4 days. To deal with that, we can borrow from Books Online and create the following function:

CREATE FUNCTION dbo.ISOWeek 
( 
    @dt SMALLDATETIME 
) 
RETURNS TINYINT 
AS 
BEGIN 
    DECLARE @ISOweek TINYINT 

    SET @ISOweek = DATEPART(WEEK,@dt)+1 
        -DATEPART(WEEK,RTRIM(YEAR(@dt))+'0104') 

    IF @ISOweek = 0 
    BEGIN 
        SET @ISOweek = dbo.ISOweek 
        ( 
            RTRIM(YEAR(@dt)-1)+'12'+RTRIM(24+DAY(@dt)) 
        ) + 1 
    END 

    IF MONTH(@dt) = 12 AND DAY(@dt)-DATEPART(DW,@dt) >= 28 
    BEGIN 
        SET @ISOweek=1 
    END 

    RETURN(@ISOweek) 
END 
GO

Then we can update the table:

UPDATE Calendar SET W = dbo.ISOWeek(dt)

另外,这里有几个关于 Numbers 的链接 table:

You REQUIRE a Numbers table!

Generate a set or sequence without loops

查找 EpiWeek:

 CREATE FUNCTION [dbo].[EPIWeek] 
( 
    @Date SMALLDATETIME 
) 
RETURNS TINYINT 
AS 
BEGIN 
    DECLARE @EPIWeek TINYINT 

    --Fix first epi week (i.e if 0401 of year falls in first week, then it will give perfect start epiweek)
    SET @EPIWeek = DATEPART(WEEK,@Date)+1 - DATEPART(WEEK,RTRIM(YEAR(@Date))+'0104') 
    --if 0401 of year falls in second week, then change to epiweek of last year
    IF @EPIWeek = 0 
    BEGIN 
        SET @EPIWeek = dbo.EPIWeek(RTRIM(YEAR(@Date)-1)+'1231')
    END 

    --Fix last epi week (ie. If any date after 2812 falls below wednesday, then it is first epiweek of next year)
    IF MONTH(@Date) = 12 AND DAY(@Date)-DATEPART(DW,@Date) >= 28 
    BEGIN 
        SET @EPIWeek=1 
    END 

    RETURN(@EPIWeek) 
END 

查找 EpiYear:

CREATE FUNCTION [dbo].[EPIYear] 
( 
    @Date DATETIME
) 
RETURNS INT
AS
BEGIN
  DECLARE @EPIYear INT = DATEPART(YEAR, @Date);

  -- WHEN January 1-3 may belong to the previous year
  IF (DATEPART(MONTH, @DATE) = 1 AND dbo.EPIWeek(@DATE) > 50)
    SET @EPIYear = @EPIYear - 1;

  -- WHEN December 29-31 may belong to the next year
  IF (DATEPART(MONTH, @DATE) = 12 AND dbo.EPIWeek(@DATE) < 45)
    SET @EPIYear = @EPIYear + 1;

  RETURN @EPIYear;

END