除自定义工作日外的所有记录的总和日期差异
Posted
技术标签:
【中文标题】除自定义工作日外的所有记录的总和日期差异【英文标题】:Sum date difference for all records excluding custom week days 【发布时间】:2018-06-30 23:37:59 【问题描述】:我在 google 搜索时发现了这个有用的查询:
SELECT
SUM((DATEDIFF(dd, vacFrom, vacTo) + 1)
-(DATEDIFF(wk, vacFrom, vacTo) * 2)
-(CASE WHEN DATENAME(dw, vacFrom)='Friday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, vacTo)='Friday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, vacFrom)='Saturday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, vacTo)='Saturday' THEN 1 ELSE 0 END))
FROM
MS_users_vacations
WHERE
YEAR(vacFrom) = 2018
它的用法例如:如果假期包括任何假期,则不包括周末,则获取员工一年的总假期天数,因此 vacFrom 是假期的开始日期vacTo 是结束日期。但是,如果周末是自定义的,如何获得相同的结果?我的意思是,如果我想对所有表记录的日期列(vacFrom、vacTo)之间的天数求和,但不包括工作日,例如:星期一和星期二或我将通过命令参数传递的任何其他日子?
【问题讨论】:
日期维度表(也称为日历维度,有时也称为时间维度)是可重复使用的,并且存在许多用于创建和填充它们的示例。一些更深思熟虑的案例包括填充美国和国际主要假期标志栏的案例陈述;当它们发生在工作日时非常有用。 您需要解释您要实现的逻辑,并提供示例数据和期望的结果。 【参考方案1】:仅使用两个辅助整数变量 DATEDIFF(Day, 0, vacFrom) 和 1+DATEDIFF(Day, 0, vacTo) - 我将其命名为 f 和 t - 您可以计算所有这些值。 例如,vacFrom-vacTo 假期的总天数为 t - f。要减去某些工作日的数量,您可以通过使用两个整数除法结果的差来计算它们的数量。例如,t/7 - f/7 是间隔中的星期日数。一般来说,区间中的“x天”数可以计算为差值
(t-x)/7 - (f-x)/7
哪里(模 7):
x = 0 表示星期日, x = 1 表示星期一, x = 2 表示星期二, x = 3 表示星期三, x = 4 表示星期四, x = 5 表示周五和 x = 6 表示星期六(我更喜欢 x = -1)。这是可行的,因为上面 DATEDIFF 表达式中使用的“日期 0”是星期一(不依赖于某些区域设置)。 因此,除周日和周六外的假期间隔天数为
(t - f) - (t/7 - f/7) - ((t+1)/7 - (f+1)/7)
您必须在这些值上构建一个 SUM(就像您在示例中所做的那样),希望按某个用户 ID 分组(您没有这样做)。
根据您的问题,如果您想排除周一和周四(我上面的列表中的 1 和 4),并且您想将这两个(当然不能等于模 7)作为参数传递给查询,您可以使用以下 T-SQL 代码(您可以改为使用存储过程或表值函数来传递这两个参数):
DECLARE @par1 int = 1 -- Mondays
, @par2 int = 4; -- Thursdays
SELECT userID
, SUM((aux.t - aux.f)
- ((aux.t-@par1)/7 - (aux.f-@par1)/7)
- ((aux.t-@par2)/7 - (aux.f-@par2)/7)
) AS vacDays
FROM MS_users_vacations
CROSS APPLY (
VALUES (DATEDIFF(Day, 0, vacFrom), 1+DATEDIFF(Day, 0, vacTo))
) aux (f, t)
WHERE YEAR(vacFrom) = 2018
GROUP BY userID;
你也可以只排除一个甚至两个以上的工作日,但如果你减去所有 7 个可能的差异,结果将为 0。:-)
【讨论】:
这是一个了不起的答案,正是我想要的。非常感谢! 谢谢你,@SherifRiad! :-)以上是关于除自定义工作日外的所有记录的总和日期差异的主要内容,如果未能解决你的问题,请参考以下文章