我有一个SQL Server表,其中包含所有员工及其病情的列表。
我需要能够计算他们在本季度患病的天数
问题是,有些人可能已经病了一年,所以,E.G的FROMDATE可能是2013-12-31而UNTILDATE可能是2014-12-31(1年病假)。但是,它应该只计算当前季度发生的疾病的天数。所以它应该是大约90天的疾病,而不是整整一年。
当前SQL
select SUM(a.WORKDAYS) as Total
from ABSENCE a
where a.FROMDATE < GETDATE() and
a.UNTILDATE > DATEADD(MONTH, -3, GETDATE())
and
a.ABS_REASON='SICK'
所以目前,这需要从任何一个正确的日期开始,因为我需要考虑那些在季度开始之前已经生病但仍然生病的人进入当前季度但是应该只计算从那个时候开始的天数。季度开始到本季度结束。
非常感谢任何帮助。
答案 0 :(得分:1)
使用日期表,您可以轻松找到日期在两个感兴趣日期之间的日期计数,以及周围存在的休假期。您还可以过滤日期以排除非工作日和公共假日。
有很多方法可以生成这样的日期表,并且在stackoverflow和dba.stackexchange上都有很多描述。
答案 1 :(得分:0)
SELECT SUM(a.WORKDAYS) as Total
FROM ABSENCE a
WHERE (a.FROMDATE >= DATEADD(MONTH, -3, GETDATE()) OR a.UNTILDATE >= DATEADD(MONTH, -3, GETDATE()))
AND a.ABS_REASON = 'SICK'
特定季度
SELECT SUM(a.WORKDAYS) as Total
FROM ABSENCE a
WHERE (a.FROMDATE >= DATEADD(quarter, -1, GETDATE()) OR a.UNTILDATE >= DATEADD(quarter, -1, GETDATE()))
AND a.ABS_REASON = 'SICK'
答案 2 :(得分:0)
不确定你的栏目。你应该只提供在2013-12-31和2014-12-31之间提供记录的sql,然后提出你的问题。
试试这个,
select SUM(Case when datepart(MM, a.FROMDATE) IN (10,11,12) Then a.WORKDAYS Else End)
as Total
from ABSENCE a
where a.FROMDATE >= '2013-12-31' and
a.UNTILDATE <= '2014-12-31'
and
a.ABS_REASON='SICK'
答案 3 :(得分:0)
使用包含所有可能日期列表的日历表非常方便,但在这种情况下,我们可以不使用它。
我会稍微概括一下你的问题。我们没有看当前季度,而是让我们有两个参数来定义您感兴趣的日期范围:
DECLARE @ParamStartDate date;
DECLARE @ParamEndDate date;
首先,我们需要从Absence
获取范围从FromDate
到UntilDate
且与给定时间段相交的所有行。
SELECT
...
FROM
Absence
WHERE
ABS_REASON='SICK'
-- all absence periods, which overlap with the given period
AND FromDate <= @ParamEndDate
AND UntilDate >= @ParamStartDate
(StartA <= EndB)
和(EndA >= StartB)
时,两个时段A和B重叠。
然后我们需要计算两个时期交叉点的天数。
交叉周期不能大于给定的日期范围(@ParamStartDate
到@ParamEndDate
)。
交叉期不能大于疾病的持续时间(FromDate
到UntilDate
)。
因此,交集的开头是FromDate
和@ParamStartDate
的最新版本,即MAX(FromDate, @ParamStartDate)
交叉点的结尾是最早的UntilDate
和@ParamEndDate
,即MIN(UntilDate, @ParamEndDate)
最后,以天为单位的交叉口的持续时间为
DATEDIFF(day, MAX(FromDate, @ParamStartDate), MIN(UntilDate, @ParamEndDate))
但是,只有它是积极的。如果是负数,则意味着疾病期在特定季度开始之前结束(或者在给定季度结束后疾病开始)。
没有内置的MIN,MAX函数可以根据需要使用两个参数,因此我使用CROSS APPLY
来计算它们。另外,我计算了给定季度的天数,只是为了完整性。最终查询如下所示:
SELECT
1+DATEDIFF(day, @ParamStartDate, @ParamEndDate) AS QuarterDays
,CASE WHEN 1+DATEDIFF(day, CTE_MaxStartDate.AbsenceStartDate, CTE_MinEndDate.AbsenceEndDate) > 0
THEN 1+DATEDIFF(day, CTE_MaxStartDate.AbsenceStartDate, CTE_MinEndDate.AbsenceEndDate)
ELSE 0 END AS AbsenceDays
FROM
Absence
CROSS APPLY
(
SELECT CASE WHEN UntilDate < @ParamEndDate THEN UntilDate ELSE @ParamEndDate END AS AbsenceEndDate
) AS CTE_MinEndDate
CROSS APPLY
(
SELECT CASE WHEN FromDate > @ParamStartDate THEN FromDate ELSE @ParamStartDate END AS AbsenceStartDate
) AS CTE_MaxStartDate
WHERE
ABS_REASON='SICK'
-- all absence periods, which overlap with the given period
AND FromDate <= @ParamEndDate
AND UntilDate >= @ParamStartDate
如果期间的开始日期和结束日期相同,我会向DATEDIFF
添加1以获得一天的持续时间。