SQL Server - 如何根据将插入数据半小时的表中的几个参数来计算持续时间?
Posted
技术标签:
【中文标题】SQL Server - 如何根据将插入数据半小时的表中的几个参数来计算持续时间?【英文标题】:SQL Server - How to sum duration based on few parameters from a table that will insert data for half an hour? 【发布时间】:2018-08-21 11:19:21 【问题描述】:为标题道歉,因为它可能与实际问题不同
我们正在为联络中心工作,我们的 SQL Server 表将捕获代理的休息时间、登录和注销的详细信息以及时间、持续时间和原因。
当代理去吃午餐 @2PM 并将其状态更改为 Break @2:10Pm 时,DB 将更新为午餐持续时间 600 秒。 IE。更改代理屏幕中的状态后,DB 将插入结束时间和因特定中断原因而发生的持续时间。
如果事件(中断)持续超过 30 分钟,则此表将每 30 分钟放置一个条目,直到代理更改其当前状态示例如下,
表格原始数据:
Agent Name SkilltargetID Event Date Time ReasonText Duration
Sathiya 5000 3 20-08-2018 10:00 BioBreak 180 Seconds
Sathiya 5000 3 20-08-2018 10:30 BioBreak 1800 Seconds
Sathiya 5000 3 20-08-2018 11:00 BioBreak 1800 Seconds
Sathiya 5000 3 20-08-2018 11:30 BioBreak 1800 Seconds
Sathiya 5000 3 20-08-2018 11:42 BioBreak 720 Seconds
Sathiya 5000 3 20-08-2018 12:01 Lunch 1140 Seconds
Sathiya 5000 3 20-08-2018 12:30 Lunch 1740 Seconds
Sathiya 5000 3 20-08-2018 12:32 Lunch 120 Seconds
Sathiya 5000 3 20-08-2018 01:00 Bio Break 1680 Seconds
Sathiya 5000 3 20-08-2018 01:29 Bio Break 1740 Seconds
我们有一个报告将显示日期、代理名称、开始时间、结束时间、ReasonText(中断原因)和持续时间。
预期输出:
Date Agent Name SkillTargetID Event Start Time End Time Reason Duration
20-08-2018 Sathiya 5000 3 9:57 AM 11:42 AM Bio Break 6300
20-08-2018 Sathiya 5000 3 12:01 AM 12:32 AM Lunch 3000
20-08-2018 Sathiya 5000 3 12:32 AM 1:29 PM Bio Break 3420
实际输出:
Date Agent Name SkillTargetID Event Start Time End Time Reason Duration
20-08-2018 Sathiya 5000 3 9:57 AM 10:00 AM Bio Break 180
20-08-2018 Sathiya 5000 3 10:00 AM 11:30 AM Bio Break 5400
20-08-2018 Sathiya 5000 3 11:30 AM 11:42 AM Bio Break 720
20-08-2018 Sathiya 5000 3 11:42 AM 12:01 AM Lunch 1140
20-08-2018 Sathiya 5000 3 12:01 AM 12:30 AM Lunch 1740
20-08-2018 Sathiya 5000 3 12:30 AM 12:32 AM Lunch 120
20-08-2018 Sathiya 5000 3 12:32 AM 1:00 AM Bio Break 1680
20-08-2018 Sathiya 5000 3 1:00 AM 1:29 AM Bio Break 1740
我们正在尝试使用以下查询来实现,
;WITH RCode ( ReasonCodeID, ReasonCode,ReasonText, Description )
AS (
Select ReasonCodeID, ReasonCode,ReasonText, Description From Reason_Code
Union All
Select 9999,0,'Not Ready-Default', 'Not Ready-System Predefined'
Union All
Select 9999,-1,'Agent reinitialized (used if peripheral restarts)', 'Not Ready-System Predefined'
Union All
Select 9999,-2,'PG reset the agent, normally due to a PG failure', 'Not Ready-System Predefined'
Union All
Select 9999,-3,'An administrator modified the agent''s extension while the agent was logged in', 'Not Ready-System Predefined'
Union All
Select 9999,50002,'A CTI OS component failed, causing the agent to be logged out', 'Not Ready-System Predefined'
Union All
Select 9999,50003,'Agent was logged out because the Unified CM reported the device out of service', 'Not Ready-System Predefined'
Union All
Select 9999,50004,'Agent was logged out due to agent inactivity as configured in agent desk settings', 'Not Ready-System Predefined'
Union All
Select 9999,50005,'The Agent will be set to not ready with this code while talking on a call on the Non ACD line', 'Not Ready-System Predefined'
Union All
Select 9999,50020,'Agent was logged out when the agent''s skill group dynamically changed on the Administration & Data Server', 'Not Ready-System Predefined'
Union All
Select 9999,50040,'Mobile agent was logged out because the call failed', 'Not Ready-System Predefined'
Union All
Select 9999,50041,'Mobile agent state changed to Not Ready because the call fails when the mobile agent''s phone line rings busy.', 'Not Ready-System Predefined'
Union All
Select 9999,50042,'Mobile agent was logged out because the phone line disconnected while using nailed connection mode', 'Not Ready-System Predefined'
Union All
Select 9999,32767,'The agent''s state was changed to Not Ready because the agent did not answer a call and the call was redirected to a different agent or skill group', 'Not Ready-System Predefined'
),
CTE ( RowNum, SerialNum, DateTime, SkillTargetID, Event, Duration, ReasonCode)
AS (
SELECT
RowNum = ROW_NUMBER() OVER (PARTITIOn BY SkillTargetID ORDER BY DateTime, SkillTargetID),
SerialNum = ROW_NUMBER() OVER (PARTITION BY SkillTargetID, Event,Duration ORDER BY DateTime),
DateTime, SkillTargetID, Event, Duration, ReasonCode
FROM
(Select DateTime,SkillTargetID, Event,
CASE WHEN (Duration=899 OR Duration=898 OR Duration=901 OR Duration=900) THEN 900
WHEN (Duration=1799 OR Duration=1798 OR Duration=1801 OR Duration=1800) THEN 1800
ELSE Duration end as 'Duration',
ReasonCode,RecoveryKey From TABLEA Where
SkillTargetID IN (5259)
And (Convert(varchar(10),DateTime,110)>= '07-10-2018' and convert(varchar(10),DateTime,110) <= '07-10-2018') ) A
)
--select * from CTE
,
CTE2 AS (
Select [Activity], Convert(varchar(10), [Activity], 101) AS [Date],
Stuff(right(convert(varchar(30), [Activity], 109), 14), 9, 4, ' ') AS [End Time],
SkillTargetID, [Agent Name], Event, [Duration], Z.ReasonCode [Reason Code], R.ReasonText [Reason], PrevDateTime,CTEDateTime, RowNum,SerialNum,PrevRow,CTENewRow From
(Select CTE.RowNum RowNum, CTE.SerialNum SerialNum, CTE.DateTime CTEDateTime, CTE.SkillTargetID,
(Select B.LastName +', '+B.FirstName From Agent (nolock) Join Person B On Agent.PersonID = B.PersonID Where SkillTargetID=CTE.SkillTargetID) [Agent Name], prev.DateTime PrevDateTime, prev.RowNum PrevRow,((CTE.RowNum-CTE.SerialNum)+1) CTENewRow,
Event = CASE WHEN CTE.Event = 1 THEN 'Sign-on' WHEN CTE.Event=2 THEN 'Sign-off' WHEN CTE.Event=3 THEN 'Not-Ready' Else 'Unknown' END,
CTE.Duration, CTE.ReasonCode,
[Activity] = CASE WHEN (CTE.Event = 3 AND CTE.Duration=1800 and CTE.SerialNum=1) THEN CTE.DateTime
WHEN (CTE.Event = 3 AND CTE.Duration=900 and CTE.SerialNum=1) THEN CTE.DateTime
WHEN (CTE.Event = 3 AND CTE.Duration=1800 and CTE.SerialNum<>1) THEN prev.DateTime
WHEN (CTE.Event = 3 AND CTE.Duration=900 and CTE.SerialNum<>1) THEN prev.DateTime
ELSE CTE.DateTime
END
FROM CTE
LEFT JOIN CTE prev ON prev.RowNum = (CTE.RowNum-CTE.SerialNum)+1 AND prev.SkillTargetID=CTE.SkillTargetID
)
Z LEFT JOIN RCode R ON R.ReasonCode = Z.ReasonCode
)
--Select * From CTE2 where [Reason Code]=107 ORDER BY Activity, [Agent Name]
Select Activity, Date, Stuff(right(convert(varchar(30), DATEADD(second, -(Sum(Duration)),[Activity]), 109), 14), 9, 4, ' ') AS [Start Time],
[End Time], SkillTargetID, [Agent Name], Event, SUM(Duration) AS [Duration], [Reason Code], Reason From CTE2
Where [Reason Code]=107
GROUP BY [Activity], Date, [End Time], SkillTargetID, [Agent Name], Event, [Reason Code], Reason
Order By [Agent Name], Activity
查询逻辑:
我们通过考虑行号和序列号来显示 TABLEA 表中的事件开始时间和结束时间,
RowNum = ROW_NUMBER() OVER (PARTITION BY SkillTargetID ORDER BY DateTime, SkillTargetID),
SerialNum = ROW_NUMBER() OVER (PARTITION BY SkillTargetID, Event,Duration ORDER BY DateTime),
来自 TABLEA。
获取 RowNum 和 SerialNum 后,我们将根据这些 RowNum 和 SerialNum 值选择一个名为 Activity 的字段,
[Activity] = CASE WHEN (CTE.Event = 3 AND CTE.Duration=1800 and CTE.SerialNum=1) THEN CTE.DateTime
WHEN (CTE.Event = 3 AND CTE.Duration=900 and CTE.SerialNum=1) THEN CTE.DateTime
WHEN (CTE.Event = 3 AND CTE.Duration=1800 and CTE.SerialNum<>1) THEN prev.DateTime
WHEN (CTE.Event = 3 AND CTE.Duration=900 and CTE.SerialNum<>1) THEN prev.DateTime
ELSE CTE.DateTime
END
FROM CTE
LEFT JOIN CTE prev ON prev.RowNum = (CTE.RowNum-CTE.SerialNum)+1 AND prev.SkillTargetID=CTE.SkillTargetID
开始时间和结束时间值基于上述[活动]。但它显示的数据不正确。
出现此问题的原因:
如果 SerialNum 基于 SkillTargetID、Event、Duration,它会为同一条目显示不同的值,并按预期为不同的条目显示 1,因此,如果我们有以下情况,我们会得到不正确的开始时间和结束时间,并且在报告。
Agent Name SkillTargetID Event Date Time ReasonText Duration
Sathiya 5000 3 20-08-2018 10:00 BioBreak 150 Seconds
Sathiya 5000 3 20-08-2018 10:30 BioBreak 1800 Seconds
Sathiya 5000 3 20-08-2018 11:00 BioBreak 1800 Seconds
Sathiya 5000 3 20-08-2018 11:30 BioBreak 1800 Seconds
Sathiya 5000 3 20-08-2018 11:42 BioBreak 720 Seconds
SerialNum 值将为第一条记录和最后一条记录显示 1,因为此查询认为它们是不同的事件并且不相同,但实际上都是相同的继续事件,应该在报告中的单行中显示。
【问题讨论】:
我建议同时格式化数据和 SQL,以便于阅读。现在您的数据没有在标题下对齐,并且由于缩进,SQL 的某些部分真的很难阅读。在 SQL Fiddle 或类似文件中提供数据也可能有助于获得答案。 @JamesZ 感谢您的评论。让我按照你说的格式化和对齐问题.. 还没有人回答,这意味着任何人都不清楚您的要求。显示。您的实际表格、预期输出并解释预期输出背后的逻辑,请一次只问一个问题。 【参考方案1】:据我了解,如果输出不正常,请重新解释要求。
样本数据,
create table #temp (AgentName varchar(50), SkilltargetID int, Events int, EventTimes datetime, ReasonText varchar(50), Duration int)
insert into #temp values
('Sathiya', 5000, 3, '2018-08-20 10:00', 'BioBreak', 180 )
,('Sathiya', 5000, 3, '2018-08-20 10:30', 'BioBreak', 1800 )
,('Sathiya', 5000, 3, '2018-08-20 11:00', 'BioBreak', 1800 )
,('Sathiya', 5000, 3, '2018-08-20 11:30', 'BioBreak', 1800 )
,('Sathiya', 5000, 3, '2018-08-20 11:42', 'BioBreak', 720 )
,('Sathiya', 5000, 3, '2018-08-20 12:01', 'Lunch', 1140 )
,('Sathiya', 5000, 3, '2018-08-20 12:30', 'Lunch', 1740 )
,('Sathiya', 5000, 3, '2018-08-20 12:32', 'Lunch', 120 )
,('Sathiya', 5000, 3, '2018-08-20 01:00', 'BioBreak', 1680 )
,('Sathiya', 5000, 3, '2018-08-20 01:29', 'BioBreak', 1740 )
脚本,
;With CTE as
(
select AgentName,SkilltargetID,Events
,ReasonText ,Duration,EventTimes
,ROW_NUMBER()over( order by(select null))rn
from #temp
)
,CTE1 as
(
select AgentName,SkilltargetID,Events
,ReasonText ,Duration,EventTimes
,rn
,1 groupid
from cte
where rn=1
union all
select c.AgentName,c.SkilltargetID,c.Events
,c.ReasonText ,c.Duration,c.EventTimes
,c.rn
,case when c.ReasonText=c1.ReasonText then groupid else groupid+1 end
from cte c
inner join cte1 c1 on c.rn=c1.rn+1
)
,cte3 as
(
select AgentName,SkilltargetID,Events,ReasonText,groupid
,ROW_NUMBER()over(partition by groupid order by EventTimes desc)rownum
,EventTimes
from CTE1
)
,cte2 as
(
select groupid,sum(duration) Duration from CTE1
group by groupid
)
select AgentName,SkilltargetID,Events,ReasonText
,convert(varchar,cast( dateadd(second,-c2.Duration, c3.EventTimes) as time),100)StartTime
,convert(varchar,cast(c3.EventTimes as time),100) EndTime
,Duration
from cte3 c3
inner join cte2 c2
on c3.groupid=c2.groupid
where c3.rownum=1
drop table #temp
【讨论】:
You Genuise.. 您的查询帮助我解决了我的问题,这正是我所期望的。谢谢@KumarHarsh ..以上是关于SQL Server - 如何根据将插入数据半小时的表中的几个参数来计算持续时间?的主要内容,如果未能解决你的问题,请参考以下文章