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 - 如何根据将插入数据半小时的表中的几个参数来计算持续时间?的主要内容,如果未能解决你的问题,请参考以下文章

第六周作业完成,一个半小时

如何设置“以属性的形式将xml数据插入到SQL Server2008数据库的表中”的存储过程

SQL Server 2008:插入不完整的数据并更新它

oracle语句 根据操作时间分组

如何将另一行中的值插入列中 - SQL Server

C# 无法将数据插入 SQL Server 数据库