我坚持使用SQL查询。我正在使用SQL Server。
给定一个包含具有开始和结束日期的作业的表。这些工作可能持续数天或数月。我需要获得与这几个月相交的所有工作的每月总工作天数。
工作
-----------------------------------
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,我将如何将其添加到结果中?
由于
答案 0 :(得分:2)
您可以使用递归CTE从每个JobID的开始到结束提取所有天数,然后逐个月份(以及我猜的年份)。
;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:在你的例子中,1月有58天而不是57;)
答案 1 :(得分: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)
答案 2 :(得分: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