我在通过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)之间的天求和,但不包括工作日,例如:星期一和星期二或我将通过命令参数传递的任何其他日子?
答案 0 :(得分: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):
之所以可行,是因为上面的DATEDIFF表达式中使用的“日期0”是星期一(不取决于某些区域设置)。 因此,假期间隔中的天数(不包括周日和周六)是
(t - f) - (t/7 - f/7) - ((t+1)/7 - (f+1)/7)
您将必须在这些值上构建一个SUM(如您在示例中所做的那样),并希望按某些userID(不是)进行分组。
以下问题,如果您想排除星期一和星期四(在上面的列表中为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。:-)