Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于计算每月工作天数的SQL查询_Sql_Sql Server_Tsql - Fatal编程技术网

用于计算每月工作天数的SQL查询

用于计算每月工作天数的SQL查询,sql,sql-server,tsql,Sql,Sql Server,Tsql,我被一个SQL查询卡住了。我正在使用SQL Server 给定一个包含具有开始和结束日期的作业的表。这些工作可以跨越几天或几个月。我需要得到每个月所有交叉工作的总工作天数 工作 我需要的结果是: Month | Days -------------- Jan | 57 Feb | 7 Mar | 28 Apr | 2 你知道我会如何纠正这样的疑问吗 我还想根据日薪乘以每个工作的工作天数计算出每个月的总和,我如何将其添加到结果中 谢谢您可以使用递归CTE提取每个JobID从开始到

我被一个SQL查询卡住了。我正在使用SQL Server

给定一个包含具有开始和结束日期的作业的表。这些工作可以跨越几天或几个月。我需要得到每个月所有交叉工作的总工作天数

工作

我需要的结果是:

Month | Days
--------------
Jan   | 57
Feb   | 7
Mar   | 28
Apr   | 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)

注:在你的例子中,一月有58天,而不是57天

您可以使用以下方法:

/* 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)

这只有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)

一个周期中的所有天都在工作还是可能有假期?所有天都在工作,不需要考虑假期。当我对数据运行它时,我得到一个错误:在语句完成之前,最大递归100已用尽。@JCoder23,哦,100是CTE的默认最大递归,以防止无限循环。您可以通过在查询-0 for infinite的末尾添加选项MAXRECURSION n来设置自己的值。查询和演示已更新。您的解决方案运行良好!我还想根据日薪乘以每个工作的工作天数计算出每个月的总和,我如何将其添加到结果中?Thanks@JCoder23或者,您可以在CTE之后执行添加步骤,在该步骤中,您还可以按JobID分组,然后加入到表中以获取费率-
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