【问题标题】:SQL Get "ISO Year" for ISO WeekSQL 获取 ISO 周的“ISO 年”
【发布时间】:2015-01-11 14:59:50
【问题描述】:

我需要计算分配给一周的年份。例如,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"

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

【问题讨论】:

  • 不要忘记添加特定 RDBMS 的标签,以吸引合适的人回答您的问题。
  • 您还需要处理第 52 周延伸到 1 月的情况(在这种情况下,您的周年比当年少一)。请参阅下面的答案。

标签: sql sql-server tsql date


【解决方案1】:

这是我能想到的最紧凑的解决方案:

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 语句的结果。

【讨论】:

  • 可以通过在 CASE 表达式之外使用 YEAR(@Date) 位来稍微缩短这一点:CASE WHEN ... THEN -1 WHEN ... THEN +1 ELSE 0 END + YEAR(@Date)
【解决方案2】:

此解决方案问题中的代码未返回日期'1-1-2027'的正确值。

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

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

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

【讨论】:

  • Nilla nilla 请不要使用第二个帐户编辑帖子。
  • 我相信这个答案确实适用于1-1-2027。结果给了我2026,这是正确的,因为1-1-2017 是星期五,这意味着 ISO 周将是 2026 年的最后一周。
  • 有点聪明。但这是有道理的
  • 26 让我头疼。我本质上有点了解发生了什么,但我想知道这里有哪些值范围。为什么是26?是的,我可以确认我的所有数据都有效。
  • 这也是一个巧合,因为我正在处理这个问题 - getdate() 已经转为 12/30/19,这是一个星期一,因此是 2020 年的第一周 :-) 新年快乐!
【解决方案3】:

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

【讨论】:

    【解决方案4】:
    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
    

    【讨论】:

      【解决方案5】:

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

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

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

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

      declare @TestDate date = '20270101'
      
      select year(dateadd(day, 3 - (datepart(weekday, @TestDate) + 6) % 8, @TestDate))
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-13
        • 2019-02-04
        • 2016-05-02
        • 2023-03-06
        • 2018-02-25
        • 2021-07-22
        • 2019-08-04
        相关资源
        最近更新 更多