SQL Server语言 - 如何根据将插入半小时数据的表中的几个参数对持续时间求和?



为标题道歉,因为它可能与实际问题不同

我们正在为联络中心工作,我们的SQL Server表将捕获座席进行休息,登录和注销的详细信息,以及时间,持续时间和原因。

当代理去吃午饭@2PM并将其状态更改为休息@2:10Pm时,DB将使用午餐持续时间600秒进行更新。在代理屏幕中更改状态后,DB 将插入结束时间和该特定中断原因发生的持续时间。

如果事件(Break(持续超过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

我们有一份报告,将显示日期,代理名称,开始时间,结束时间,原因文本(中断原因(和持续时间。

预期输出:

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),

来自表。

获取 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、事件、持续时间,则它为同一条目显示不同的值,并按预期为不同的条目显示 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,因为此查询认为它们是不同的事件并且不同,但实际上都是相同的继续事件,应该显示在报告中的单行中。

根据我的理解,如果输出不正常,那么请注意重新解释要求。

样本数据,

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

最新更新