这可能是一个相当简单的问题,但我在任何地方都找不到简单的解决方案。有没有办法计算两个日期之间的 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]
此更新产生所需的输出。
在 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