这比看起来难。我需要一个函数来计算日期范围内给定工作日的数量。我不需要任何循环或递归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
@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值两个函数返回的结果不一致。
7
DATEDIFF(wk)
DATEPART(dw)
DATEFIRST
因此,必须修改上述脚本,以便在计算时考虑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,正如有人在这里建议的那样。
-@@DATEFIRST % 7
-@@DATEFIRST