SQL获得ISO Week的“ISO年份”

时间:2014-11-14 09:00:08

标签: sql sql-server tsql date

我需要计算每周分配的年份。例如,2003年12月29日被分配到2004年的第一周(我想这只适用于欧洲)。您可以使用以下代码查看此内容:

SELECT DATEPART(isowk, '20141229');

但现在我需要一个简单的方法来分配本周的年份。我目前所做的并不那么优雅:

DECLARE @week int, @year int, @date char(8)

--set @date = '20150101'
set @date = '20141229'


SET @week = cast(datepart(isowk, @date) as int)

if @week = 1
begin
      if DATEPART(MONTH, @date) = 12
      begin
            set @year = DATEPART(year, @date) + 1
      end
      else
      begin
            set @year = DATEPART(year, @date)
      end
end

select @date "DATE", @week "WEEK", @year "YEAR"

如果有人知道更优雅的方式,那就太好了: - )

5 个答案:

答案 0 :(得分:7)

此解决方案未返回日期'1-1-2027'的正确值。

以下将返回正确的值,包括我测试的所有日期(我测试了很多)。

SELECT YEAR(DATEADD(day, 26 - DATEPART(isoww, '2012-01-01'), '2012-01-01'))

取自:https://capens.net/content/sql-year-iso-week

答案 1 :(得分:3)

这是我能提出的最紧凑的解决方案:

CASE
    WHEN DATEPART(ISO_WEEK, @Date) > 50 AND MONTH(@Date) = 1 THEN YEAR(@Date) - 1
    WHEN DATEPART(ISO_WEEK, @Date) = 1 AND MONTH(@Date) = 12 THEN YEAR(@Date) + 1
    ELSE YEAR(@Date) END

可以直接在SELECT语句中使用。或者您可以考虑创建一个用户定义的函数,该函数将@Date参数作为输入并输出case语句的结果。

答案 2 :(得分:0)

对于IsoYear,从IsoWeek获得星期四,然后获得年份。

答案 3 :(得分:0)

我认为这个解决方案对于 ISO-8601 来说更合乎逻辑,也更容易理解。

“一年中的第一周是包含第一个星期四的那一周。” 见ISO Week definition

所以我们需要从星期四减去给定日期的工作日并将其添加到同一日期以获得年份。

编辑:添加 6,然后取 8 的模数将星期日移到前一周。

declare @TestDate date = '20270101'

select year(dateadd(day, 3 - (datepart(weekday, @TestDate) + 6) % 8, @TestDate))

这将导致 2026,这是正确的。

答案 4 :(得分:-1)

DECLARE @date DATETIME
SET @date='2014-12-29'
SELECT 
CASE --Covers logic for ISO week date system which is part of the ISO 8601 date and time standard.  Ref: https://en.wikipedia.org/wiki/ISO_week_date
  WHEN (DATEPART(ISO_WEEK,@date) = 53) AND (DATEPART(MONTH,@date) = 1)
    THEN CAST((DATEPART(YEAR, @date) - 1) AS varchar(4)) + ('-W') + CAST (RIGHT('0' + CAST(DATEPART(ISO_WEEK,@date) AS varchar(2)),2) AS varchar(2))
  WHEN (DATEPART(ISO_WEEK,@date) = 1) AND (DATEPART(MONTH,@date) = 12)
    THEN CAST((DATEPART(YEAR,@date) + 1) AS varchar(4)) + ('-W') + CAST (RIGHT('0' + CAST(DATEPART(ISO_WEEK,@date) AS varchar(2)),2) AS varchar(2))
  ELSE CAST(DATEPART(YEAR,@date) AS varchar(4)) + ('-W') + CAST (RIGHT('0' + CAST(DATEPART(ISO_WEEK,@date) AS varchar(2)),2) AS varchar(2))
 END AS ISO_week