2014-12-16 7 views
6

모든 직원 목록과 병이 들어있는 SQL Server 테이블이 있습니다. 그들은 현재 분기에 아픈 있었다 얼마나 많은 일이 문제는, 어떤 사람들은 그렇게 년 동안 아픈되었을 수도 있습니다SQL 병계 일

, 예를 들어 FROMDATE가 2013-12-이 될 수

내가 계산 할 수 있어야합니다 UNTILDATE는 2014-12-31 (1 년 병가) 일 수 있습니다. 그러나 그것은 단지 현재의 분기에 일어나는 그 병으로부터의 일을 계산해야합니다. 따라서 1 년 내내 계산하는 것이 아니라 약 90 일간의 병이 있어야합니다.

그래서 순간, 그것은 내가하지만 현재 분기로 예정 분기가 시작되기 전에 이미 아픈했다하지만 여전히 아픈 사람들을 고려하여 필요에 따라 올바른 어떤 FROMDATE에서 소요

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' 

현재 SQL 분기가 시작된 후 분기가 끝날 때까지 일 수를 계산해야합니다.

도움을 주시면 감사하겠습니다.

+1

'ABSENCE'테이블의 샘플 데이터를 공유 할 수 있습니까? –

+1

분기가 끝나기 전에 시작하여 분기가 시작된 후에 끝난 모든 결석이 필요합니다 (그들이 언제 돌아 오는지 모를 경우 'NULL'입니다). 따라서 WHERE 절은 다음과 같습니다. 올바른 ('NULL'' UNTILDATE'를 처리 할 필요가 없다면). 그러면 현재 분기 및 부재 범위 내의 일 수를 계산해야하며 이에 대해 Rob Farley가 제안한대로 작업 일을 알 필요가 있습니다. –

답변

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' 
+1

누군가가 장기간 병에 걸리면 1 년이 넘었을 수도 있습니다. 그것은 단지 현재 분기의 범위에서 아픈 일수를 계산해야합니다. –

+1

논리는 지난 3 개월 간의 병가를 계산하는 것입니다. – Matt

+0

업데이트 된 대답은 현재 분기의 모든 결석을 포함합니다. – Matt

1

특정 분기, 쉽게 날짜의 수를 찾을 수 그것. 비 근무일 및 공휴일을 제외하기 위해 날짜를 필터링 할 수도 있습니다.

이러한 날짜 테이블을 생성하는 데는 여러 가지 방법이 있지만 stackoverflow와 dba.stackexchange에 모두 설명되어 있습니다.

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' 
0

가능한 모든 날짜의 목록이있는 달력 테이블을 갖는 것은 편리하지만,이 경우 우리는 그것없이 할 수 있습니다.

질문을 일반화 해 드리겠습니다. 대신 이번 분기에서 바로보고의에서의 당신이 관심이 날짜의 범위를 정의하는 두 개의 매개 변수를 보자 : 우리가 FromDate에서 UntilDate의 범위를 Absence에서 모든 행을 얻을 필요가 먼저

DECLARE @ParamStartDate date; 
DECLARE @ParamEndDate date; 

그 주어진 기간과 교차합니다.

SELECT 
    ... 
FROM 
    Absence 
WHERE 
    ABS_REASON='SICK' 
    -- all absence periods, which overlap with the given period 
    AND FromDate <= @ParamEndDate 
    AND UntilDate >= @ParamStartDate 

두 기간 A와 B의 겹치는 경우 및 (StartA <= EndB)(EndA >= StartB).

그러면 두 기간의 교집합 일 수를 계산해야합니다.

교차로는 주어진 날짜 범위보다 클 수 없습니다 (@ParamStartDate에서 @ParamEndDate).

교차로는 병의 길이보다 클 수 없습니다 (FromDate에서 UntilDate).

그래서, 교차로의 시작, FromDate@ParamStartDate의 최신 즉 MAX(FromDate, @ParamStartDate)

교차로의 결말은의, 즉 MIN(UntilDate, @ParamEndDate)

마지막으로, 기간, 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 

나는 기간의 시작 날짜와 종료 날짜가 같은 경우 1 일의 기간을 얻을 수 DATEDIFF에 1을 추가합니다.

+1

@DavidHayward, 어떻게 결국 문제를 해결 했습니까? 제공된 답 중 어떤 것이 유용 했습니까? 그렇다면, 당신은 그들을 upvote 수 있으며 가장 유용한 한 가지 대답을 수락하십시오. –