繁体   English   中英

查找未接来电30分钟内客户服务部门完成的回电话数

[英]Find the number of return calls that were done by customer care within 30 minutes of the missed call

考虑接收客户呼叫的客户服务中心,Starttime和Endtime表示会话开始时间和结束时间。 未接来电是没有发生对话的电话。 对于任何未接来电,客户服务部门都会回复电话。

对于下面给出的表,

CREATE TABLE CustomerCare (fromnumber INT, tonumber INT, starttime DATETIME,endtime DATETIME)

INSERT INTO CustomerCare (fromnumber,tonumber,starttime,endtime) 
VALUES
(100,1800,'2019-08-13 18:40:00','2019-08-13 18:40:00'),
(1800,100,'2019-08-13 18:55:00','2019-08-13 18:57:00'),
(200,1800,'2019-08-13 19:30:00','2019-08-13 19:30:00'),
(1800,200,'2019-08-13 20:05:00','2019-08-13 20:10:00'),
(300,1800,'2019-08-13 21:00:00','2019-08-13 21:00:00'),
(1800,300,'2019-08-13 21:20:00','2019-08-13 21:25:00'),
(400,1800,'2019-08-13 07:00:00','2019-08-13 07:00:00'),
(500,1800,'2019-08-13 8:00:00','2019-08-13 8:05:00')

在此输入图像描述

查找未接来电30分钟内客户服务部门完成的回电话数。

第四行表示一个这样的回叫。

任何人都可以帮助SQL查询。

首先你找到未接来电,然后你会发现客户服务的回电。 你发现时间不同了

select  *
from    CustomerCare mc
        cross apply -- get call back time
        (   
            select  top 1 *
            from    CustomerCare x
            where   x.fromnumber    = mc.tonumber
            and     x.tonumber  = mc.fromnumber
            and     x.starttime > mc.starttime
            order by x.starttime
        ) cb
where   mc.starttime = mc.endtime  -- missed call
and     datediff(minute, mc.starttime, cb.starttime) > 30 -- time different between 
                                                          -- missed call and callback

@Squirrel打败了我,我的答案原来的答案基本上与他相同,但我会发布我放在一起的内容,因为它也说明为什么APPLY如此优秀。

首先,为了获得最佳性能,您需要在启动时使用聚簇索引(或覆盖索引)。 例如

CREATE CLUSTERED INDEX CL_CustomerCare_starttime ON dbo.CustomerCare(starttime);

接下来,这是你如何使用JOIN(因为你提到它)来做到这一点:

SELECT 
  cc.fromnumber,
  cc.tonumber, 
  missedcalltime = CAST(CAST(cc.starttime AS TIME) AS CHAR(5)),
  callbacktime   = CAST(CAST(x.starttime AS TIME) AS CHAR(5)),
  timetocallback = datediff(minute, cc.starttime, x.starttime)
FROM   dbo.CustomerCare AS cc
JOIN   dbo.CustomerCare AS x
  ON   cc.tonumber = x.fromnumber
 AND   x.tonumber  = cc.fromnumber
 AND   cc.starttime < x.starttime
WHERE datediff(minute, cc.starttime, x.starttime) <= 30;

现在,APPLY版本(这是我在看到松鼠回答之前放在一起的):

SELECT 
  cc.fromnumber,
  cc.tonumber, 
  missedcalltime = CAST(CAST(cc.starttime AS TIME) AS CHAR(5)),
  callbacktime   = CAST(CAST(x.starttime AS TIME) AS CHAR(5)),
  timetocallback = cb.t
FROM   dbo.CustomerCare AS cc
CROSS APPLY 
(
  SELECT TOP (1) x.starttime
  FROM     dbo.CustomerCare AS x
  WHERE    cc.tonumber = x.fromnumber
  AND      x.tonumber  = cc.fromnumber
  AND      cc.starttime < x.starttime
  ORDER BY x.starttime
) AS x
CROSS APPLY (VALUES(datediff(minute, cc.starttime, x.starttime))) AS cb(t)
WHERE       cb.t <= @callback;

两者都归来:

fromnumber  tonumber    missedcalltime callbacktime timetocallback
----------- ----------- -------------- ------------ --------------
100         1800        18:40          18:55        15
300         1800        21:00          21:20        20

关于APPLY的第一个很酷的事情是如何使用它来为值设置别名以使我的代码“DRYer”。 (DRY =不要重复自己)。 由于表达式为datediff(minute, cc.starttime, x.starttime)多次使用,我可以使用APPLY处理表达式,然后多次引用它作为cb.t. 注意这一行:

CROSS APPLY (VALUES(datediff(minute, cc.starttime, x.starttime))) AS cb(t)

这是APPLY如何使代码更清晰,更容易调试的示例。

关于APPLY强大功能的第二个也许更重要的例子是如何使用子查询加入外部查询。 我上面的两个例子并不完全相同。 从理论上讲,如果在30分钟内有多个“回叫”,JOIN版本将返回它们。 由于这可能是一个边缘情况,在半小时内要求“TOP(1)”返回呼叫就足够了,并且性能会更好。 如果检查两个查询的执行计划 - 当连接到CustomerCare时,连接版本会读取更多行(28),APPLY版本将读取22行。 如果在APPLY版本中将TOP(1)更改为TOP([任何大于1]),它将读取28行。 同样,这是另一种可以使用APPLY来调整性能的方法。

最后,关于子查询中TOP的重要注释...如果在APPLY子查询中删除ORDER BY,则当存在正确索引列的ORDER BY时,子查询将读取58行而不是22行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM