当我第一次开始在 sql 世界中寻找这个问题的答案时,我夜以继日地搜索。找不到与我的需求类似的任何东西,所以我决定提出并回答我自己的问题,以防其他人像我一样需要帮助。
这是我拥有的数据的示例。为简单起见,这一切都来自 Job 表。每个 JobID 都有自己的开始和结束时间,它们基本上是随机的,可以重叠、有间隙、与其他作业同时开始和结束等。
--Available--
JobID WorkerID JobStart JobEnd
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-19 18:30'
4 25 '2012-11-19 17: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'
我希望查询结果显示的是:
WorkerID TotalTime(in Mins)
25 170
26 120
编辑:忘了提到重叠需要被忽略。基本上,这应该像对待小时工而不是承包商一样对待这些工人及其工作。就像我工作了两个 jobID 并从下午 12:00 到 12:30 开始和完成它们一样,作为员工,我只能获得 30 分钟的报酬,而承包商可能会获得 60 分钟的报酬,因为他们的工作是单独对待的,而且每份工作获得报酬。此查询的目的是分析数据库中与工人相关的工作,并且需要找出该工人是否被视为雇员,他在给定时间内的总工作时间是多少。
EDIT2: 7 小时内不让我回答我自己的问题,稍后将其移到那里。
好的,现在回答问题。基本上,我使用临时表在我正在查找的作业的最小和最大日期时间之间构建每一分钟。
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-19 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
现在我有一个临时表中的所有分钟。现在我需要将所有作业表信息加入其中,并一次性选择我需要的内容。
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 --Thanks ErikE
GROUP BY J.WorkerID --Thanks Martin Parkin
drop table #time
这是一个非常简单的答案,很适合让某人开始。