我对one posted here有类似的问题。
我将使用相同的DDL。但我也只改变了一个值,以说明它的不同之处。
就像这个例子一样,我也有员工在不同的开始和结束时间工作许多不同的工作,当工作时间重叠时,我不想计算任何重叠的分钟数。不同的是,在我的情况下,有些工作会在午夜到第二天进行,我不希望在第二天将工作时数作为第一天报告时间的一部分。
`USE Sandbox
GO
--CREATE TABLE Job
--(
-- JobID INT NOT NULL,
-- WorkerID INT NOT NULL,
-- JobStart DATETIME NOT NULL,
-- JobEnd DATETIME NOT NULL
--);
--INSERT INTO Job2 (JobID, WorkerID, JobStart, JobEnd)
--VALUES
--(1, 25, '2012-11-17 16:00', '2012-11-17 17:00'),
--(2, 25, '2012-11-18 16:00', '2012-11-18 16:50'),
--(3, 25, '2012-11-19 18:00', '2012-11-20 18:30'),
--(4, 25, '2012-11-19 18:30', '2012-11-19 18:10'),
--(5, 26, '2012-11-18 16:00', '2012-11-18 17:10'),
--(6, 26, '2012-11-19 16:00', '2012-11-19 16:50');
IF OBJECT_ID('tempdb..#time') IS NOT NULL
BEGIN
drop table #time
END
DECLARE @FromDate AS DATETIME,
@ToDate AS DATETIME,
@Current AS DATETIME
SET @FromDate = '2012-11-17 16:00'
SET @ToDate = '2012-11-20 18:30'
create table #time (cte_start_date datetime)
set @current = @FromDate
while (@current < @ToDate)
begin
insert into #time (cte_start_date)
values (@current)
set @current = DATEADD(n, 1, @current)
end
----query to edit
SELECT J.WorkerID
,COUNT(DISTINCT t.cte_start_date) AS TotalTime
FROM #time AS t
INNER JOIN Job2 AS J ON t.cte_start_date >= J.JobStart AND t.cte_start_date < J.JobEnd
GROUP BY J.WorkerID
drop table #time`
参见JobID = 3,工作从2012-11-19 18:00开始,直到2012-11-20 18:30,第二天才结束。
结果集应为:
WorkerID 26 TotalTime 120
WorkerID 25 TotalTime 470 (and not 1580)
如何修改此查询,以便仅将6小时的jobID 3分配给11-19工作的小时数,另外6.5小时分配给11-20工作小时数?
答案 0 :(得分:0)
您只需要确保临时表中的所有时间都与开始日期在同一天。我将仅发布修改后的select
部分,其余部分保持不变。
在SQL Server 2008或更高版本中:
SELECT J.WorkerID
,COUNT(DISTINCT t.cte_start_date) AS TotalTime
FROM #time AS t
INNER JOIN Job AS J ON t.cte_start_date >= J.JobStart AND t.cte_start_date < J.JobEnd
and dateadd(d, 0, t.cte_start_date as date) = cast(J.JobStart as date)
GROUP BY J.WorkerID
在SQL Server 2005及更低版本上:
SELECT J.WorkerID
,COUNT(DISTINCT t.cte_start_date) AS TotalTime
FROM #time AS t
INNER JOIN Job AS J ON t.cte_start_date >= J.JobStart AND t.cte_start_date < J.JobEnd
and DateAdd(d, 0, DateDiff(d, t.cte_start_date, 0)) = DateAdd(d, 0, DateDiff(d, J.JobStart, 0))
GROUP BY J.WorkerID
修改强>
您可以使用以下查询获取每个日期的时间(按午夜分割) - 完整查询:
DECLARE @FromDate AS DATETIME,
@ToDate AS DATETIME,
@Current AS DATETIME
SET @FromDate = '2012-11-17 16:00'
SET @ToDate = '2012-11-21 18:30'
create table #time (cte_start_date datetime)
set @current = @FromDate
while (@current < @ToDate)
begin
insert into #time (cte_start_date)
values (@current)
set @current = DATEADD(n, 1, @current)
end
--query to edit
SELECT J.WorkerID, CAST(t.cte_start_date as date) as WorkedDate
,COUNT(DISTINCT t.cte_start_date) AS TotalTime
FROM #time AS t
INNER JOIN Job AS J ON t.cte_start_date >= J.JobStart AND t.cte_start_date < J.JobEnd
GROUP BY J.WorkerID, CAST(t.cte_start_date as date)
答案 1 :(得分:0)
这会将跨越两天的工作分成他们自己的记录,每天一个,然后应用您已有的算法。请注意,如果作业可能超过两天,则无效:
;with JobByDay( Day, JobId, WorkerId, StartTime, EndTime )
as
(
select
CAST( JobStart as Date ) Day
, JobId
, WorkerId
, JobStart StartTime
, EndTime = case
when CAST( JobStart as Date ) < CAST( JobEnd as Date )
then dateadd( dd, 1, CAST( JobStart as Date ) )
else JobEnd
end
from
Job
union
select
CAST( JobEnd as Date ) Day
, JobId
, WorkerId
, Cast( JobEnd as Date ) StartTime
, JobEnd EndTime
from
Job
where
CAST( JobStart as Date ) < CAST( JobEnd as Date )
)
select
*
from
JobByDay
order by
WorkerId, Day