我有一个操作员表,我想计算一整天两个状态(10-20)之间的时差。
这里我想要" ActivityStatus"之间的时差。 10和20。 我们在这张照片中共有3组10-20状态。对于最后一个状态,在这种情况下没有20状态它将采用最后一个oa_createdDate(即oa_id 230141)。
此运算符的预期输出是cl_id 230096和230102之间的日期差异,cl_id 230103和230107之间的日期差异,cl_id 230109和cl_id 230141之间的日期差异。一旦我得到这些差异,我想将所有日期差异值加总到计算该运营商的繁忙时间。
提前致谢。
答案 0 :(得分:1)
我怀疑DateDiff()函数是你寻找的函数
答案 1 :(得分:1)
有一种简单的方法可以做我认为你想做外部应用的事情,就像这样:
select tmin.*, t.oa_CreateDate oa_CreateDate_20
, datediff(minute, tmin.oa_CreateDate, t.oa_CreateDate) DiffInMinutes
from testtable t
cross apply
(select top 1 *
from testtable tmin
where tmin.oa_CreateDate < t.oa_CreateDate and tmin.oa_OperatorId = t.oa_OperatorId
order by tmin.oa_CreateDate asc) tmin
where t.ActivityStatus = 20
and t.oa_CreateDate < (select min(oa_CreateDate) from testtable where ActivityStatus = 10 and oa_OperatorId = 1960)
and t.oa_OperatorId = 1960
union all
select t.*
, coalesce(a.oa_CreateDate,ma.MaxDate) oa_CreateDate_20
, datediff(minute, t.oa_CreateDate, coalesce(a.oa_CreateDate,ma.MaxDate)) DiffInMinutes
from testtable t
outer apply
(select top 1 a.oa_CreateDate
from testtable a
where a.oa_OperatorId = t.oa_OperatorId and a.ActivityStatus = 20
and t.oa_CreateDate < a.oa_CreateDate order by a.oa_CreateDate asc) a
outer apply
(select max(a2.oa_CreateDate) maxDate
from testtable a2
where a2.oa_OperatorId = t.oa_OperatorId
and t.oa_CreateDate < a2.oa_CreateDate) ma
where oa_OperatorId = 1960
and ActivityStatus = 10
order by oa_CreateDate asc, oa_CreateDate_20 asc
你可以看到小提琴here。
但是,当然,你必须给我们格式/ accurracy for datediff比较。这假设您将始终同时具有状态10和20,并且它们的时间戳范围永远不会重叠。
编辑:根据您的评论更新答案,检查新脚本并提琴。现在脚本填充找到所有状态10 - 20日期值,如果在最后10个之后没有状态20,则将使用该状态10之后的最新现有时间戳。
编辑2:更新了以下评论。但在这一点上,剧本变得相当丑陋。不幸的是我没有时间来清理它,所以我要求你下次发一个问题时,请尽可能清楚地把它弄清楚,因为这样做的回答要少得多。问题一次,而不是沿着骑行编辑3个不同的变化。 :)
无论如何,这应该可行,脚本中UNION ALL之前的新部分只有在没有前面10的状态20的情况下才会返回结果。否则它将不返回任何内容,并像以前一样移动到脚本的主要部分。小提琴也已更新。
答案 2 :(得分:0)
这是一种做法。
第一个OUTER APPLY
将检索当前创建的日期时间之后状态为20的下一行。
第二个OUTER APPLY
将检索当前创建的日期时间之后没有状态20的下一行。
SELECT
o.*
, COALESCE(NextStatus.oa_CreateDate, NextStatusIsNull.oa_CreateDate) AS NextTimestamp
, COALESCE(NextStatus.ActivityStatus, NextStatusIsNull.ActivityStatus) AS NextStatus
, DATEDIFF(MINUTE, o.oa_CreateDate,
COALESCE(NextStatus.oa_CreateDate, NextStatusIsNull.oa_CreateDate))
AS DifferenceInMinutes
FROM
operators AS o
OUTER APPLY
(
SELECT TOP 1
oa_CreateDate
, ActivityStatus
FROM
operators
WHERE
ActivityStatus = 20
AND oa_CreateDate > o.oa_CreateDate
ORDER BY
oa_CreateDate
) AS NextStatus
OUTER APPLY
(
SELECT TOP 1
oa_CreateDate
, ActivityStatus
FROM
operators
WHERE
NextStatus.oa_CreateDate IS NULL
AND oa_CreateDate > o.oa_CreateDate
ORDER BY
oa_CreateDate
) AS NextStatusIsNull
WHERE
ActivityStatus = 10
答案 3 :(得分:0)
我使用了一些不同的测试数据,因为您使用了我无法剪切和粘贴的图片。这应该很容易转换为您的表格:
请注意,这也适用于不存在的开始和结束日期
另请注意,这样做没有任何连接来优化性能。
测试表和数据:
DECLARE @t table(ActivityStatus int, oa_createdate datetime, oa_operatorid int)
INSERT @t values
(30, '2015-07-23 08:20', 1960),(20, '2015-07-23 08:24', 1960),
(10, '2015-07-23 08:30', 1960),(20, '2015-07-23 08:40', 1960),
(10, '2015-07-23 08:50', 1960),(50, '2015-07-23 09:40', 1960)
查询:
;WITH cte as
(
SELECT
ActivityStatus,
oa_createdate,
oa_operatorid
FROM @t
WHERE ActivityStatus in (10,20)
UNION ALL
SELECT 20, max(oa_createdate), oa_operatorid
FROM @t
GROUP BY oa_operatorid
HAVING
max(case when ActivityStatus = 20 then oa_createdate end) <
max(case when ActivityStatus = 10 then oa_createdate end)
UNION ALL
SELECT 10, min(oa_createdate), oa_operatorid
FROM @t
GROUP BY oa_operatorid
HAVING
min(case when ActivityStatus = 20 then oa_createdate end) <
min(case when ActivityStatus = 10 then oa_createdate else '2999-01-01' end)
)
SELECT
cast(cast(sum(case when activitystatus = 10 then -1 else 1 end
* cast(oa_createdate as float)) as datetime) as time(0)) as difference_in_time,
oa_operatorid
FROM cte
GROUP BY oa_operatorid
结果:
difference_in_time oa_operatorid
01:04:00 1960
答案 4 :(得分:0)
数据强>
create table #Table2 (oa_id int, oa_OperatorId int, ActivityStatus int, oa_CreateDate datetime)
insert into #Table2
values (1, 1960,10,'2015-08-10 10:55:12.317')
,(2, 1960,20,'2015-08-10 11:55:12.317')
,(3, 1960,30,'2015-08-10 14:55:12.317')
,(4, 1960,50,'2015-08-10 14:58:12.317')
,(5, 1960,10,'2015-08-10 15:55:12.317')
,(6, 1960,20,'2015-08-10 16:20:12.317')
,(7, 1960,10,'2015-08-10 16:30:12.317')
,(8, 1960,50,'2015-08-10 17:20:12.317')
使用我们感兴趣的行填充目标表
select oa_id,
oa_operatorid,
ActivityStatus,
oa_createDate,
rn = row_number() over (order by oa_id desc)
into #Table
from #Table2
where ActivityStatus in (10, 20)
insert #Table
select top 1
oa_id,
oa_operatorid,
ActivityStatus,
oa_createDate,
0
from #Table2
order by oa_id desc
select * into #Table10 from #Table where ActivityStatus = 10
select * into #Table20 from #Table where ActivityStatus = 20
union
select * from #Table where rn = 0 /*add the last record*/
except
select * from #Table where rn = (select max(rn) from #Table) /**discard the first "20" record*/
/*free time info*/
select datediff(second, t10.oa_createDate, t20.oa_createDate) secondssincelast10,
t20.*
from #Table10 t10 join #Table20 t20
on t10.rn = t20.rn + 1
and t10.oa_OperatorId = t20.oa_OperatorId
/*Summarized info per operator*/
select sum(datediff(second, t10.oa_createDate, t20.oa_createDate)) totalbusytime,
t20.oa_OperatorId
from #Table10 t10 join #Table20 t20
on t10.rn = t20.rn + 1
and t10.oa_OperatorId = t20.oa_OperatorId
group by t20.oa_OperatorId
答案 5 :(得分:-1)
最好的方式
DATEDIFF(expr1,expr2)
示例:
CREATE TABLE pins
(`id` int, `time` datetime)
;
INSERT INTO pins
(`id`, `time`)
VALUES
(1, '2013-11-15 05:25:25')
;
SELECT DATEDIFF(CURDATE(), `time`)
FROM `pins`