【发布时间】:2017-09-07 02:01:25
【问题描述】:
epi-week 的定义如下:
“根据定义,一年中的第一个 Epi 周在 1 月的第一个星期六结束,只要它在该月至少四天。每个 Epi 周从星期日开始,到星期六结束。”
参考:1
我用服务器语言 (C#/Java) 实现了它们,但我的问题是从 SQL Server 存储过程返回一个 Epi 周和 Epi 年
【问题讨论】:
标签: sql sql-server datepart
epi-week 的定义如下:
“根据定义,一年中的第一个 Epi 周在 1 月的第一个星期六结束,只要它在该月至少四天。每个 Epi 周从星期日开始,到星期六结束。”
参考:1
我用服务器语言 (C#/Java) 实现了它们,但我的问题是从 SQL Server 存储过程返回一个 Epi 周和 Epi 年
【问题讨论】:
标签: sql sql-server datepart
如果您还没有 Calendar 表,我强烈建议您在数据库中创建它。
这是一个表格,在足够长的时间内每天都有一行,足以满足您的需求。
在此类表中添加一列 EpiWeek 并填充一次。然后在您需要的任何地方使用,而不是即时计算。
日历表在许多领域都很有用,并有助于使用基于 SQL 集的查询来解决各种问题。日历表是Numbers 表的特例,也经常有用。
详细示例见:
Why should I consider using an auxiliary calendar table?
这篇文章有一个关于 ISO 周数的部分。我不确定 ISO 周和 Epi 周是否相同,但您可以查看 Aaron Bertrand 如何计算 ISO 周数的示例:
很多很多人对 SQL Server 计算周数的方式不满意。它在
DATEPART(WEEK, <date>)中使用的奇怪算法并不总是产生与 ISO 标准相同的数字,ISO 标准规定第 1 周是第一周有 4 天。为了解决这个问题,我们可以借用 Books Online 并创建以下函数: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然后我们可以更新表格:
UPDATE Calendar SET W = dbo.ISOWeek(dt)
另外,这里有几个关于数字表的链接:
【讨论】:
查找 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
【讨论】: