Sql 所有记录(不包括自定义周天数)的合计日期差

Sql 所有记录(不包括自定义周天数)的合计日期差,sql,sql-server,Sql,Sql Server,我在谷歌搜索时发现了这个有用的查询: 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)

我在谷歌搜索时发现了这个有用的查询:

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)之间的天数求和,但不包括工作日,如:星期一和星期二,或我将通过命令参数传递的任何其他日期?

只使用两个辅助整数变量,DATEDIFF(Day,0,vacFrom)和1+DATEDIFF(Day,0,vacTo)-我将其命名为f和t-您可以计算所有这些值。 例如,从vacTo休假到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表达式中使用的“date 0”是星期一(不依赖于某些区域设置)。 因此,不包括星期日和星期六的假期间隔天数为

(t - f) - (t/7 - f/7) - ((t+1)/7 - (f+1)/7)
您必须在这些值上构建一个总和(就像您在示例中所做的那样),希望通过一些userID进行分组(您没有这样做)

根据您的问题,如果您想排除星期一和星期四(我上面列表中的1和4),并且希望将这两个(当然不能等于模7)作为参数传递给查询,则可以使用以下T-SQL代码(您可以使用存储过程或表值函数传递这两个参数):


您也可以仅排除一个或两个以上的工作日,但如果减去所有7个可能的差异,结果将为0.:-)

日期维度表(也称为日历维度,有时也称为时间维度)是可重用的,并且存在许多创建和填充它们的示例。其中一些更为深思熟虑的案例包括:在美国和国际重大节日的旗帜栏中填写案例说明;当它们发生在工作日时非常有用。你需要解释你想要实现的逻辑,并提供样本数据和期望的结果。这是一个令人惊讶的答案,正是我想要的。谢谢!谢谢你,@SherifRiad!:-)
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;