计算两个日期之间的 ISO_WEEK(可能跨年)

问题描述 投票:0回答:2

这可能是一个相当简单的问题,但我在任何地方都找不到简单的解决方案。有没有办法计算两个日期之间的 ISO_WEEK(也可能跨越多年)而不减去 ISO_WEEK 值本身?

如果我减去下面的 ISO 周数,我会得到 -47
2024年12月1日 = W48
2024年12月31日 = W01
预期结果应该是 5

如果我减去下面的 ISO 周数,我会得到 -47
2022-01-01 = W52
2022年1月31日 = W05
预期结果应该是 6

如果我减去下面的 ISO 周数,我会得到 0
2022-01-01 = W52
2022年12月31日 = W52
预期结果应该是 53

如果我减去下面的 ISO 周数,我会得到 -3
2022年12月31日 = W01
2023-01-26 = W04
预期结果应该是 5

这是我用来测试的 SQL 的两个部分:
此处的目的是为了计费目的计算上个月的 ISO 周数。添加了一个条件,如果该周已在上一次迭代中使用围绕该月第一个星期日的条件逻辑进行计费,则从上个月删除 1 周。

DECLARE @D DATE = '2025-01-01'

SELECT  DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0) AS FOM
        , DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0)) AS FOM_ISOWEEK#
        , DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, -1, @D)-1, -1))-DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0))+1 AS ISOWEEK_COUNT
        , DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, -1, @D)-1, -1)) AS EOM_ISOWEEK#
        , DATEADD(MONTH, DATEDIFF(MONTH, -1, @D)-1, -1) AS EOM
        , DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 0 - DATEPART(DAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0)), DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0))), 6) AS FSUNDAY
        , CASE  WHEN DATEDIFF(DAY, (DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0)), (DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 0 - DATEPART(DAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0)), DATEADD(MONTH, DATEDIFF(MONTH, 0,    @D)-1, 0))), 6)))+1 < 7
                THEN DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, -1, @D)-1, -1))-DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0))
                ELSE DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, -1, @D)-1, -1))-DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0))+1 END AS [SUM]
DECLARE @DD DATE = '2022-02-01'

SELECT  DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0) AS FOM
        , DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0)) AS FOM_ISOWEEK#
        , DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, -1, @DD)-1, -1))-DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0))+1 AS ISOWEEK_COUNT
        , DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, -1, @DD)-1, -1)) AS EOM_ISOWEEK#
        , DATEADD(MONTH, DATEDIFF(MONTH, -1, @DD)-1, -1) AS EOM
        , DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 0 - DATEPART(DAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0)), DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0))), 6) AS FSUNDAY
        , CASE  WHEN DATEDIFF(DAY, (DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0)), (DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 0 - DATEPART(DAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0)), DATEADD(MONTH, DATEDIFF(MONTH, 0,  @DD)-1, 0))), 6)))+1 < 7
                THEN DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, -1, @DD)-1, -1))-DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0))
                ELSE DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, -1, @DD)-1, -1))-DATEPART(ISO_WEEK,DATEADD(MONTH, DATEDIFF(MONTH, 0, @DD)-1, 0))+1 END AS [SUM]

一切正常,除非减法跨越多年。我在上面提供了两个发生这种情况的例子。

更新
我进行了一些简化,并找到了一个合理的解决方法here。更新逻辑如下:

DECLARE     @D DATE = '2025-01-01'
            
DECLARE     @FOM DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0)
            , @EOM DATE = DATEADD(MONTH, DATEDIFF(MONTH, -1, @D)-1, -1)

SELECT  @FOM AS FOM
        , DATEPART(ISO_WEEK,@FOM) AS FOM_ISOWEEK#
        , DATEDIFF(dd,0,@EOM)/7 - DATEDIFF(dd,0,@FOM)/7 +1 AS ISOWEEK_COUNT
        , DATEPART(ISO_WEEK,@EOM) AS EOM_ISOWEEK#
        , @EOM AS EOM
        , DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 0 - DATEPART(DAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0)), DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0))), 6) AS FSUNDAY
        , CASE  WHEN DATEDIFF(DAY, (DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0)), (DATEADD(WEEK, DATEDIFF(WEEK, 0,DATEADD(DAY, 0 - DATEPART(DAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, @D)-1, 0)), DATEADD(MONTH, DATEDIFF(MONTH, 0,    @D)-1, 0))), 6)))+1 < 7
                THEN DATEDIFF(dd,0,@EOM)/7 - DATEDIFF(dd,0,@FOM)/7
                ELSE DATEDIFF(dd,0,@EOM)/7 - DATEDIFF(dd,0,@FOM)/7 +1 END AS [SUM]

此更新产生所需的输出。

sql sql-server iso week-number
2个回答

0
投票

在 Spark SQL 中,我使用嵌套在 date_diff 中的 date_trunc 函数来执行此操作。

date_trunc('week',TestDate) 将返回给定日期的 ISO 8601 周的开始日期。 因此,如果我们在 date _diff 函数中对开始日期和结束日期执行此操作

    WITH 
DateList AS 
  (
      SELECT explode(sequence(CAST('2024-01-01' AS date), CAST('2025-02-01' AS date), interval 1 day)) as TestDate
  )

SELECT
  CAST(TestDate AS DATE) 
, weekofyear(TestDate)AS WeekNumber
, concat(extract(YEAROFWEEK FROM TestDate),' W',lpad(weekofyear(TestDate), 2, '0')) AS WeekOfYear
, date_diff(week,date_trunc('week',TestDate) ,date_trunc('week',now())) AS WeeksAgo

FROM DateList
© www.soinside.com 2019 - 2024. All rights reserved.