(If using SQL Server 2022 or later, see the much simpler answer from Charlieface.)个
给定定义任何两周时段的第一个星期一的参考日期,您可以计算天数差,然后计算FLOOR(diff / 14.0)
以获得时段编号,或计算((diff % 14) + 14) % 14
以计算相对于包含两周时段的开始星期一的天数.
要处理负偏移,需要使用FLOOR(diff / 14.0)
,而不是只使用diff / 14
.同样,((diff % 14 + 14) % 14
中的双模数也需要将负数映射到所需的0..13范围.
DECLARE @ReferenceDate DATE = '2023-10-02' -- Reference Monday
;WITH CTE_Dates AS (
SELECT CONVERT(DATETIME, '2023-09-01 13:45') Dt
UNION ALL
SELECT DATEADD(day, 1, D.Dt) AS Dt
FROM CTE_Dates D
WHERE D.Dt < '2023-10-31'
)
SELECT
D.Dt,
DATENAME(weekday, D.Dt) AS WeekDay,
DATEDIFF(day, @ReferenceDate, D.Dt) AS DayDiff,
FLOOR(DATEDIFF(day, @ReferenceDate, D.Dt) / 14.0) AS BucketNo,
((DATEDIFF(day, @ReferenceDate, D.Dt) % 14) + 14) % 14 AS BucketDay,
CONVERT(DATE, DATEADD(day, - ((DATEDIFF(day, @ReferenceDate, D.Dt) % 14) + 14) % 14, D.Dt)) AS BucketStartDt,
CONVERT(DATE, DATEADD(day, 13 - ((DATEDIFF(day, @ReferenceDate, D.Dt) % 14) + 14) % 14, D.Dt)) AS BucketEndDt
FROM CTE_Dates D
OPTION (MAXRECURSION 1000)
部分结果:
Dt |
WeekDay |
DayDiff |
BucketNo |
BucketDay |
BucketStartDt |
BucketEndDt |
2023-10-01 13:45 |
Sunday |
-1 |
-1 |
13 |
2023-09-18 |
2023-10-01 |
2023-10-02 13:45 |
Monday |
0 |
0 |
0 |
2023-10-02 |
2023-10-15 |
2023-10-03 13:45 |
Tuesday |
1 |
0 |
1 |
2023-10-02 |
2023-10-15 |
2023-10-04 13:45 |
Wednesday |
2 |
0 |
2 |
2023-10-02 |
2023-10-15 |
2023-10-05 13:45 |
Thursday |
3 |
0 |
3 |
2023-10-02 |
2023-10-15 |
2023-10-06 13:45 |
Friday |
4 |
0 |
4 |
2023-10-02 |
2023-10-15 |
2023-10-07 13:45 |
Saturday |
5 |
0 |
5 |
2023-10-02 |
2023-10-15 |
2023-10-08 13:45 |
Sunday |
6 |
0 |
6 |
2023-10-02 |
2023-10-15 |
2023-10-09 13:45 |
Monday |
7 |
0 |
7 |
2023-10-02 |
2023-10-15 |
2023-10-10 13:45 |
Tuesday |
8 |
0 |
8 |
2023-10-02 |
2023-10-15 |
2023-10-11 13:45 |
Wednesday |
9 |
0 |
9 |
2023-10-02 |
2023-10-15 |
2023-10-12 13:45 |
Thursday |
10 |
0 |
10 |
2023-10-02 |
2023-10-15 |
2023-10-13 13:45 |
Friday |
11 |
0 |
11 |
2023-10-02 |
2023-10-15 |
2023-10-14 13:45 |
Saturday |
12 |
0 |
12 |
2023-10-02 |
2023-10-15 |
2023-10-15 13:45 |
Sunday |
13 |
0 |
13 |
2023-10-02 |
2023-10-15 |
2023-10-16 13:45 |
Monday |
14 |
1 |
0 |
2023-10-16 |
2023-10-29 |
2023-10-17 13:45 |
Tuesday |
15 |
1 |
1 |
2023-10-16 |
2023-10-29 |
2023-10-18 13:45 |
Wednesday |
16 |
1 |
2 |
2023-10-16 |
2023-10-29 |
2023-10-19 13:45 |
Thursday |
17 |
1 |
3 |
2023-10-16 |
2023-10-29 |
请参见this db<>fiddle.
最初的帖子和随后的 comments 对于哪些星期一构成为期两周的桶的开始或中间并不一致,但可以根据需要更改@ReferenceDate
个,以适应最终决定.(今天甚至不需要是星期一.)