📌  相关文章
📜  sql 计算两个日期之间的工作日,不包括周末和节假日 - SQL (1)

📅  最后修改于: 2023-12-03 15:20:17.672000             🧑  作者: Mango

SQL计算两个日期之间的工作日

在很多业务场景下,需要计算两个日期之间的工作日,常常需要排除掉周末以及一些特殊节假日等,以便得到准确的工作日天数。本文介绍如何用SQL实现这样一个计算工作日的功能。

实现思路

在SQL中,可以使用以下步骤来计算两个日期之间的工作日:

  1. 首先,生成一个日期范围,包含起始日期和结束日期之间的所有日期。
  2. 其次,根据日期范围中所有日期的星期几信息,去掉所有周末的日期。
  3. 最后,根据自定义的节假日信息,去掉所有特殊节假日的日期。
实现步骤
步骤一:生成日期范围

为了生成日期范围,可以使用T-SQL的CTE(Common Table Expression)特性,结合row_number()函数来实现。具体的方法如下:

;with DateRange as
(
    select [date], ROW_NUMBER() over (order by [date]) as rn
    from (
        select dateadd(day, number, [start_date]) as [date]
        from master..spt_values
        where type = 'P' and dateadd(day, number, [start_date]) <= [end_date]
    ) as D
)

在上述代码中,使用master..spt_values系统表来生成一个数值序列,然后将每个数字加上起始日期,并筛选出只包含在起始日期和结束日期范围内的日期。最后,使用ROW_NUMBER()函数来给每个日期编号,以方便后续操作。

步骤二:去掉周末的日期

为了去掉周末的日期,可以使用DATEPART()函数来获取每个日期的星期几信息,具体的SQL代码如下:

select [date], datepart(weekday, [date]) as weekday
from DateRange

在上述代码中,使用datepart()函数来获取每个日期的星期几信息,并将其作为一个新列添加到查询结果中。

接着,为了去掉所有周末的日期,可以在上述SQL查询的基础上,添加一个WHERE子句,来筛选出所有非周末的日期,具体的SQL代码如下:

where datepart(weekday, [date]) not in (1,7)

在上述代码中,使用not in运算符来排除所有星期六和星期天的日期。

步骤三:去掉特殊节假日的日期

为了去掉特殊节假日的日期,我们需要先定义一个自定义的节假日表,其中包含所有需要去除的特殊日期。比如,假设我们的自定义节假日表为Holiday,其中包含以下节假日:

| HolidayDate | | ----------- | | 2022-01-01 | | 2022-02-01 | | 2022-02-02 | | ... |

那么,我们可以在上述SQL查询的基础上,添加一个LEFT JOIN操作,将每个日期与Holiday表中的节假日进行比对,并将匹配到的日期从查询结果中去除,具体的SQL代码如下:

left join Holiday on [date] = HolidayDate
where HolidayDate is null

在上述代码中,使用LEFT JOIN操作将每个日期与Holiday表中的节假日进行比对,并使用where子句将匹配到的日期从查询结果中去除。

完整代码

下面是实现计算两个日期之间的工作日的完整SQL代码片段,其中包含了上述所有步骤的实现:

declare @start_date date = '2022-01-01', @end_date date = '2022-01-31'

;with DateRange as
(
    select [date], ROW_NUMBER() over (order by [date]) as rn
    from (
        select dateadd(day, number, @start_date) as [date]
        from master..spt_values
        where type = 'P' and dateadd(day, number, @start_date) <= @end_date
    ) as D
)
select [date], datepart(weekday, [date]) as weekday
from DateRange
left join Holiday on [date] = HolidayDate -- 假设已经定义了节假日表Holiday
where datepart(weekday, [date]) not in (1,7) and HolidayDate is null
总结

以上就是用SQL计算两个日期之间的工作日的实现方法。虽然在具体业务场景中,需要根据不同的需求自定义生成日期范围、去除周末和节假日的逻辑,但是基本思路是相似的。熟练掌握这个方法,将有助于我们在很多业务场景下快速计算工作日天数。