SQL 填充 2 周时间表的日历日期
Posted
技术标签:
【中文标题】SQL 填充 2 周时间表的日历日期【英文标题】:SQL populating calendar dates for 2 week timetable 【发布时间】:2020-08-28 15:34:41 【问题描述】:我有两张表,一张用于时间表日期:
+--------+---------+
| intDay | DayName |
+--------+---------+
| 1 | Mon A |
| 2 | Tue A |
| 3 | Wed A |
| 4 | Thu A |
| 5 | Fri A |
| 6 | Mon B |
| 7 | Tue B |
| 8 | Wed B |
| 9 | Thu B |
| 10 | Fri |
+--------+---------+
还有一个带有学期日期的表格:
+-----------+------------+------------+
| Term Name | Term Start | Term End |
+-----------+------------+------------+
| Term A | 07/09/2020 | 15/12/2020 |
| Term B | 10/01/2021 | 15/03/2021 |
| Term C | 01/04/2021 | 03/07/2021 |
+-----------+------------+------------+
我可以使用第三个表格,其中包含日历周数以及是 A 周还是 B 周。
这个结构是:
+-------------+---------+---------+
| intYearWeek | intYear | intWeek |
+-------------+---------+---------+
| 37 | 2020 | 1 |
| 38 | 2020 | 2 |
| 39 | 2020 | 1 |
| 40 | 2020 | 2 |
| 41 | 2020 | 1 |
| 42 | 2020 | 2 |
+-------------+---------+---------+
intYearWeek 是一年中的日历周数,intYear 是学年(9 月至 7 月),A 周和 B 周分别表示为 1 或 2。这些只是教学周,因此不包括任何假期周。
我想做的是使用上述两周周期生成整个学年的日历日期列表,但仅限于学期期间。我会将这些与教职员工和学生的时间表相匹配,以生成 Outlook 导入。
因此,如果我们采用第 37-40 周(2020 年 9 月 7 日 - 2020 年 9 月 28 日),结果将如下所示:
+-----------------+------------+
| Week_Number Day | Date |
+-----------------+------------+
| 37 Mon A | 07/09/2020 |
| 37 Tue A | 08/09/2020 |
| 37 Wed A | 09/09/2020 |
| 37 Thu A | 10/09/2020 |
| 37 Fri A | 11/09/2020 |
| 38 Mon B | 14/09/2020 |
| 38 Tue B | 15/09/2020 |
| 38 Wed B | 16/09/2020 |
| 38 Thu B | 17/09/2020 |
| 38 Fri B | 18/09/2020 |
| 39 Mon A | 21/09/2020 |
| 39 Tue A | 22/09/2020 |
| 39 Wed A | 23/09/2020 |
| 39 Thu A | 24/09/2020 |
| 39 Fri A | 25/09/2020 |
| 40 Mon B | 28/09/2020 |
| 40 Tue B | 29/09/2020 |
| 40 Wed B | 30/09/2020 |
| 40 Thu B | 01/10/2020 |
| 40 Fri B | 02/10/2020 |
+-----------------+------------+
提前感谢您的帮助!
【问题讨论】:
请向我们展示您想要的结果。 您使用的是哪种 DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称(日期/时间函数是特定于供应商的)。请为您正在使用的数据库产品添加tag。 Why should I tag my DBMS @GMB 我已经添加了结果和我正在使用的数据库产品(SQL Server 2019)。抱歉,我不知道如何格式化表格。 我认为有必要在正确的年份进行细分和大小写,并将 1/2 与 A/B 相匹配,即使如此,第 37 周的报告如何包括第 40 周也有点失落。 @DavidG.Pickett 我已经编辑了结果,结果显示的是从学期开始算起的 4 周,而不仅仅是第一周。 【参考方案1】:方法:
-
使用递归公用表表达式 (
cte_TermDays
) 创建学年开始到学年结束之间的所有日期。
过滤掉周末和学期以外的日子(where
子句)。
将星期几与星期类型结合起来确定星期 A 或 B 并获取日期名称。
样本数据
create table TermPeriods
(
Name nvarchar(6),
StartDate date,
EndDate date
);
insert into TermPeriods (Name, StartDate, EndDate) values
('Term A', '2020-09-07', '2020-12-15'),
('Term B', '2021-01-10', '2021-03-15'),
('Term C', '2021-04-01', '2021-07-03');
create table DayNames
(
dayNum int,
dayName nvarchar(5)
);
insert into DayNames (dayNum, dayName) values
( 1, 'Mon A'),
( 2, 'Tue A'),
( 3, 'Wed A'),
( 4, 'Thu A'),
( 5, 'Fri A'),
( 6, 'Mon B'),
( 7, 'Tue B'),
( 8, 'Wed B'),
( 9, 'Thu B'),
(10, 'Fri B');
create table WeekTypes
(
YearNum int,
WeekNum int,
WeekType int
);
insert into WeekTypes (YearNum, WeekNum, WeekType) values
(2020, 37, 1),
(2020, 38, 2),
(2020, 39, 1),
(2020, 40, 2),
(2020, 41, 1),
(2020, 42, 2);
解决方案
with cte_TermDays as
(
select min(StartDate) as [TermDate], max(EndDate) as [Stop]
from TermPeriods
union all
select dateadd(day, 1, td.TermDate), td.Stop
from cte_TermDays td
where td.TermDate < td.Stop
)
select td.TermDate as [Date],
datepart(DW, td.TermDate)-1 as [DayPart],
datepart(WW, td.TermDate) as [WeekPart],
datepart(YY, td.TermDate) as [YearPart],
wt.WeekType,
(datepart(DW, td.TermDate)-1)+(wt.WeekType-1)*5 as [DayNum],
dn.DayName,
convert(nvarchar(2), wt.WeekNum) + ' ' + dn.DayName as [Week_Number Day]
from cte_TermDays td
join WeekTypes wt
on wt.YearNum = datepart(YY, td.TermDate)
and wt.WeekNum = datepart(WW, td.TermDate)
join DayNames dn
on dn.DayNum = (datepart(DW, td.TermDate)-1)+(wt.WeekType-1)*5
where datepart(DW, td.TermDate) > 1 --exclude sunday
and datepart(DW, td.TermDate) < 7 --exclude saturday
and exists ( select top 1 'x' --limit to term periods
from TermPeriods tp
where tp.StartDate <= td.TermDate
and tp.EndDate >= td.TermDate )
order by td.TermDate
option (maxrecursion 366);
结果
Date DayPart WeekPart YearPart WeekType DayNum DayName Week_Number Day
---------- ----------- ----------- ----------- ----------- ----------- ------- ---------------
2020-09-07 1 37 2020 1 1 Mon A 37 Mon A
2020-09-08 2 37 2020 1 2 Tue A 37 Tue A
2020-09-09 3 37 2020 1 3 Wed A 37 Wed A
2020-09-10 4 37 2020 1 4 Thu A 37 Thu A
2020-09-11 5 37 2020 1 5 Fri A 37 Fri A
2020-09-14 1 38 2020 2 6 Mon B 38 Mon B
2020-09-15 2 38 2020 2 7 Tue B 38 Tue B
2020-09-16 3 38 2020 2 8 Wed B 38 Wed B
2020-09-17 4 38 2020 2 9 Thu B 38 Thu B
2020-09-18 5 38 2020 2 10 Fri B 38 Fri B
2020-09-21 1 39 2020 1 1 Mon A 39 Mon A
2020-09-22 2 39 2020 1 2 Tue A 39 Tue A
2020-09-23 3 39 2020 1 3 Wed A 39 Wed A
2020-09-24 4 39 2020 1 4 Thu A 39 Thu A
2020-09-25 5 39 2020 1 5 Fri A 39 Fri A
2020-09-28 1 40 2020 2 6 Mon B 40 Mon B
2020-09-29 2 40 2020 2 7 Tue B 40 Tue B
2020-09-30 3 40 2020 2 8 Wed B 40 Wed B
2020-10-01 4 40 2020 2 9 Thu B 40 Thu B
2020-10-02 5 40 2020 2 10 Fri B 40 Fri B
2020-10-05 1 41 2020 1 1 Mon A 41 Mon A
2020-10-06 2 41 2020 1 2 Tue A 41 Tue A
2020-10-07 3 41 2020 1 3 Wed A 41 Wed A
2020-10-08 4 41 2020 1 4 Thu A 41 Thu A
2020-10-09 5 41 2020 1 5 Fri A 41 Fri A
2020-10-12 1 42 2020 2 6 Mon B 42 Mon B
2020-10-13 2 42 2020 2 7 Tue B 42 Tue B
2020-10-14 3 42 2020 2 8 Wed B 42 Wed B
2020-10-15 4 42 2020 2 9 Thu B 42 Thu B
2020-10-16 5 42 2020 2 10 Fri B 42 Fri B
【讨论】:
非常感谢!这是一个很好的解决方案以上是关于SQL 填充 2 周时间表的日历日期的主要内容,如果未能解决你的问题,请参考以下文章