2013-07-25 4 views
2

SQL 쿼리에서 멈춤. SQL Server를 사용하고 있습니다.월당 근무일 수를 계산하는 SQL 쿼리

시작 및 종료 날짜가있는 작업이 포함 된 테이블이 제공됩니다. 이러한 작업은 며칠 또는 수개월이 걸릴 수 있습니다. 그 달을 교차시킨 모든 직업에 대해 매월 일한 총 합산 일수를 알아야합니다.

채용

----------------------------------- 
JobId | Start | End | DayRate | 
----------------------------------- 
1  | 1.1.13 | 2.2.13 | 2500 | 
2  | 5.1.13 | 5.2.13 | 2000 | 
3  | 3.3.13 | 2.4.13 | 3000 | 

내가 필요 결과는 다음과 같습니다

Month | Days 
-------------- 
Jan | 57 
Feb | 7 
Mar | 28 
Apr | 2 

어떤 생각을 내가 어떻게 것 바로 이러한 쿼리?

각 작업에 대해 근무일 수를 곱한 결과에 따라 매월 SUM을 계산할 수 있습니다. 결과에이를 어떻게 추가 할 수 있습니까?

감사

+2

을 기간의 모든 일 근무, 아니면 휴일이있을 수 있습니까? –

+0

모든 요일이 작동하며 휴일을 고려할 필요가 없습니다. – JCoder23

답변

2
당신은 (내가 추측 년) 월별로 그럼 그냥 그룹을 각 작업 ID에 대한 종료하고 처음부터 모든 일을 추출하는 재귀 CTE 사용할 수 있습니다

.

;WITH CTE_TotalDays AS 
(
    SELECT [Start] AS DT, JobID FROM dbo.Jobs 
    UNION ALL 
    SELECT DATEADD(DD,1,c.DT), c.JobID FROM CTE_TotalDays c 
    WHERE c.DT < (SELECT [End] FROM Jobs j2 WHERE j2.JobId = c.JobID) 
) 
SELECT 
    MONTH(DT) AS [Month] 
    ,YEAR(DT) AS [Year] 
    ,COUNT(*) AS [Days] 
FROM CTE_TotalDays 
GROUP BY MONTH(DT),YEAR(DT) 
OPTION (MAXRECURSION 0) 

SQLFiddle DEMO

PS : 58 당신의 예에서 1 월 일이 아니라 57이 있습니다)

+0

내 데이터에 대해 실행할 때 오류가 발생합니다. 명령문 완료 전에 최대 재귀 100이 모두 소모되었습니다. – JCoder23

+0

좋아, 내가 MAXRECURSIONS 옵션을 추가하고 0으로 설정, 잘 작동합니다. – JCoder23

+0

@ JCoder23, Oh, 100은 무한 루프를 방지하기 위해 CTE의 기본 최대 재귀입니다. 무한의 질의 끝에 0을 추가하여 자신 만의 값을 설정할 수있다. 쿼리 및 데모가 업데이트되었습니다. –

0

당신은 다음과 같은 방식 사용하여 수행 할 수 있습니다

/* Your table with periods */ 
declare @table table(JobId int, Start date, [End] date, DayRate money) 

INSERT INTO @table (JobId , Start, [End], DayRate) 
VALUES 
(1, '20130101','20130202', 2500), 
(2,'20130105','20130205', 2000), 
(3,'20130303','20130402' , 3000) 

/* create table where stored all possible dates 
    if this code are supposed to be executed often you can create 
    table with dates ones to avoid overhead of filling it */ 
declare @dates table(d date) 

declare @d date='20000101' 
WHILE @d<'20500101' 
    BEGIN 
     INSERT INTO @dates (d) VALUES (@d) 
     SET @d=DATEADD(DAY,1,@d) 
    END; 

/* and at last get desired output */ 

SELECT YEAR(d.d) [YEAR], DATENAME(month,d.d) [MONTH], COUNT(*) [Days] 
FROM @dates d 
    CROSS JOIN @table t 
WHERE d.d BETWEEN t.Start AND t.[End] 
GROUP BY YEAR(d.d), DATENAME(month,d.d) 
0

이를 각 행마다 1 대신 1 개의 재귀 호출 만 있습니다. 나는 당신이 많은 양의 데이터를 가지고있을 때 이것이 선택된 대답보다 잘 수행 될 것이라고 상상한다.

declare @t table(JobId int, Start date, [End] date, DayRate int) 
insert @t values 
(1,'2013-01-01','2013-02-02', 2500),(2,'2013-01-05','2013-02-05', 2000),(3,'2013-03-03', '2013-04-02',3000) 

;WITH a AS 
(

SELECT min(Start) s, max([End]) e 
FROM @t 
), b AS 
(
SELECT s, e from a 
UNION ALL 
SELECT dateadd(day, 1, s), e 
FROM b WHERE s <> e 
) 
SELECT 
    MONTH(b.s) AS [Month] 
    ,YEAR(b.s) AS [Year] 
    ,COUNT(*) AS [Days] 
    ,SUM(DayRate) MonthDayRate 
FROM b 
join @t t 
on b.s between t.Start and t.[End] 
GROUP BY MONTH(b.s),YEAR(b.s) 
OPTION (MAXRECURSION 0) 

결과 :

Month Year Days MonthDayRate 
1  2013 58  131500 
2  2013 7  15000 
3  2013 29  87000 
4  2013 2  6000 
관련 문제