小编典典

TSQL中日期范围内的工作日数

sql

这比看起来难。我需要一个函数来计算日期范围内给定工作日的数量。我不需要任何循环或递归SQL。数以百万计的示例就是这样做的。我需要一个快速函数来进行计算。

该函数的输入将是工作日,fromdata,迄今为止

-- counting fridays
set datefirst 1
SELECT dbo.f_countweekdays(5, '2011-07-01', '2011-07-31'),
dbo.f_countweekdays(5, '2011-07-08', '2011-07-15'),
dbo.f_countweekdays(5, '2011-07-09', '2011-07-15'),
dbo.f_countweekdays(5, '2011-07-09', '2011-07-14')

预期结果:

5, 2, 1, 0

阅读 209

收藏
2021-03-23

共1个答案

小编典典

@Mikael Eriksson有一个绝妙的主意,但是他的实现似乎有些复杂:

ALTER FUNCTION dbo.f_countweekdays (@Dow int, @StartDate datetime, @EndDate datetime)
RETURNS int
AS BEGIN
  RETURN (
    SELECT
      DATEDIFF(wk, @StartDate, @EndDate)
      - CASE WHEN DATEPART(dw, @StartDate) > @Dow THEN 1 ELSE 0 END
      - CASE WHEN DATEPART(dw, @EndDate)   < @Dow THEN 1 ELSE 0 END
      + 1
  )
END

更新

正如Mikael在其答案的注释线程中正确指出的那样,为了使上述解决方案正确运行,必须将DATEFIRST设置设置为7(Sunday)。尽管我找不到此文档,但快速测试发现它DATEDIFF(wk)忽略了实际的DATEFIRST设置,实际上返回了以周为单位的差值,就好像DATEFIRST始终设置为7。同时DATEPART(dw)尊重了DATEFIRST,因此DATEFIRST设置为other值两个函数返回的结果不一致。

因此,必须修改上述脚本,以便在计算时考虑DATEFIRST设置的不同值DATEDIFF(wk)。令人高兴的是,修复似乎并没有取得该解决方案
比以前复杂,在我看来。不过,请自行判断:

ALTER FUNCTION dbo.f_countweekdays (@Dow int, @StartDate datetime, @EndDate datetime)
RETURNS int
AS BEGIN
  RETURN (
    SELECT
      DATEDIFF(wk, DATEADD(DAY, -@@DATEFIRST, @StartDate),
                   DATEADD(DAY, -@@DATEFIRST, @EndDate))
      - CASE WHEN DATEPART(dw, @StartDate) > @Dow THEN 1 ELSE 0 END
      - CASE WHEN DATEPART(dw, @EndDate)   < @Dow THEN 1 ELSE 0 END
      + 1
  )
END

编辑: 这两个-@@DATEFIRST % 7条目都简化为just
-@@DATEFIRST,正如有人在这里建议的那样。

2021-03-23