每行之间具有固定时间跨度的 SQL 连续行

Posted

技术标签:

【中文标题】每行之间具有固定时间跨度的 SQL 连续行【英文标题】:SQL consecutive rows with a fixed time span between each row 【发布时间】:2017-01-26 22:28:12 【问题描述】:

*** 的好人, 请提供一些帮助... 所以我们这里有一个表格......包含客户打给某个联络中心(HelpDesk 或其他)的电话。

-----------------------------------------------------------------------
|   DateD  |   DateM   |    Date_Time    |EMPL_ID| PHONE_NO |FIRST_REP |
|----------------------------------------------------------------------
|2016-12-12| 2016-12-01| 2016-12-12 15:55| 16652 | 123456789| First    |
|2016-12-22| 2016-12-01| 2016-12-22 10:42| 18178 | 123456789| First    |
|2016-12-22| 2016-12-01| 2016-12-22 10:54|112981 | 123456789| Repeat   |
|2016-12-22| 2016-12-01| 2016-12-22 10:57| 18179 | 123456789| Repeat   |
|2016-12-23| 2016-12-01| 2016-12-23 12:27| 16653 | 123456789| Repeat   |
|2017-01-05| 2017-01-01| 2017-01-05 15:20| 17896 | 123456789| First    |
|2017-01-11| 2017-01-01| 2017-01-11 15:48| 17909 | 123456789| Repeat   |
|2017-01-18| 2017-01-01| 2017-01-18 10:07| 18175 | 123456789| Repeat   |
|2016-12-03| 2016-12-01| 2016-12-03 20:32| 17745 | 111222333| First    |
|2016-12-21| 2016-12-01| 2016-12-21 18:47| 10982 | 111222333| First    |
|2016-12-22| 2016-12-01| 2016-12-22 15:53| 17820 | 111222333| Repeat   |
|2016-12-28| 2016-12-01| 2016-12-28 13:07| 15976 | 111222333| Repeat   |
|2016-12-29| 2016-12-01| 2016-12-29 21:35| 17896 | 111222333| Repeat   |
|2016-12-29| 2016-12-01| 2016-12-29 21:46| 15498 | 111222333| Repeat   |
|2017-01-02| 2017-01-01| 2017-01-02 16:24| 13117 | 111222333| Repeat   |
-----------------------------------------------------------------------

我想做的是弄清楚,重复了多少次呼叫,这意味着客户再次呼叫。 现在棘手的部分是重复呼叫被定义为源自“第一次呼叫”的呼叫,并且在第一次呼叫后的每次交互的 7 天时间跨度内连续重复,例如:

----------------------------------------------------------------------------
|   DateD   |    DateM   |    Date_Time     |EMPL_ID|  PHONE_NO |FIRST_REP |
|---------------------------------------------------------------------------
|2016-12-01 | 2016-12-12 | 2016-12-12 15:55 | 16652 | 123456789 | First    |
|2016-12-01 | 2016-12-22 | 2016-12-22 10:42 | 18178 | 123456789 | First    |
|2016-12-01 | 2016-12-22 | 2016-12-22 10:54 | 112981| 123456789 | Repeat   |
|2016-12-01 | 2016-12-22 | 2016-12-22 10:57 | 18179 | 123456789 | Repeat   |
|2016-12-01 | 2016-12-23 | 2016-12-23 12:27 | 16653 | 123456789 | Repeat   |
|2017-01-01 | 2017-01-05 | 2017-01-05 15:20 | 17896 | 123456789 | First    |
|2017-01-01 | 2017-01-11 | 2017-01-11 15:48 | 17909 | 123456789 | Repeat   |
|2017-01-01 | 2017-01-18 | 2017-01-18 10:07 | 18175 | 123456789 | Repeat   |
----------------------------------------------------------------------------

我们有: 第一行是第一次呼叫,没有重复呼叫, 第 2 行是第一次呼叫,有 3 次重复呼叫,因为每次交互都在从第一次呼叫开始的每个前一次的 7 天时间跨度内 第 3 行是第一次调用,有 2 次重复调用,就像上面一样。

现在我们想说的是,ID 为 16652 的员工(第一行)产生了 0 次重复调用,而 ID 为 18178 的员工则产生了 3 次重复调用。

最后,如果有一些方法可以创建这样的输出,那就太好了:

|   DateM   |    DateD   |     Date_Time    |EMP_ID |  PHONE_NO |FIRST_REP | DateM_REP  | DateD_REP  | Date_Time_REP    | EMP_ID_REP | PHONE_NO_REP | FIRST_REP_REP
|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|2016-12-01 | 2016-12-12 | 2016-12-12 15:55 | 16652 | 123456789 |   First  |    null    |    null    |       null       |   null     |    null      | null
|2016-12-01 | 2016-12-22 | 2016-12-22 10:42 | 18178 | 123456789 |   First  | 2016-12-01 | 2016-12-22 | 2016-12-22 10:54 |   112981   |   123456789  | Repeat
|2016-12-01 | 2016-12-22 | 2016-12-22 10:42 | 18178 | 123456789 |   First  | 2016-12-01 | 2016-12-22 | 2016-12-22 10:57 |   18179    |   123456789  | Repeat
|2016-12-01 | 2016-12-22 | 2016-12-22 10:42 | 18178 | 123456789 |   First  | 2016-12-01 | 2016-12-23 | 2016-12-23 12:27 |   16653    |   123456789  | Repeat
|2017-01-01 | 2017-01-05 | 2017-01-05 15:20 | 17896 | 123456789 |   First  | 2017-01-01 | 2017-01-11 | 2017-01-11 15:48 |   17909    |   123456789  | Repeat
|2017-01-01 | 2017-01-05 | 2017-01-05 15:20 | 17896 | 123456789 |   First  | 2017-01-01 | 2017-01-18 | 2017-01-18 10:07 |   18175    |   123456789  | Repeat

请帮忙,我不太擅长编写 CTE,而且我认为这是一个有可能通过 CTE 解决的问题。

非常感谢LuKI


编辑:

CREATE TABLE t_calls
(
[DateM] date,
[DateD] date,
[Date_Time] datetime2(7),
[EMPL_ID] int,
[INTERACTION_ID] numeric(25,0),
[PHONE_NO] numeric(9,0),
[FIRST_REP] varchar(10)
)

Insert Into t_calls

([DateM],[DateD],[Date_Time],[EMPL_ID],[INTERACTION_ID],[PHONE_NO],[FIRST_REP])
Values 
('2016-12-01 00:00:00','2016-12-12 00:00:00','2016-12-12 15:55:36',16652,340680165,123456789,'First')
,('2016-12-01 00:00:00','2016-12-22 00:00:00','2016-12-22 10:42:45',18178,343736497,123456789,'First')
,('2016-12-01 00:00:00','2016-12-22 00:00:00','2016-12-22 10:54:46',112981,343750151,123456789,'Repeat')
,('2016-12-01 00:00:00','2016-12-22 00:00:00','2016-12-22 10:57:29',18179,343750151,123456789,'Repeat')
,('2016-12-01 00:00:00','2016-12-23 00:00:00','2016-12-23 12:27:56',16653,344071359,123456789,'Repeat')
,('2017-01-01 00:00:00','2017-01-05 00:00:00','2017-01-05 15:20:47',17896,347063121,123456789,'First')
,('2017-01-01 00:00:00','2017-01-11 00:00:00','2017-01-11 15:48:20',17909,348429965,123456789,'Repeat')
,('2017-01-01 00:00:00','2017-01-18 00:00:00','2017-01-18 10:07:45',18175,350243945,123456789,'Repeat')
,('2016-12-01 00:00:00','2016-12-03 00:00:00','2016-12-03 20:32:37',17745,338392721,111222333,'First')
,('2016-12-01 00:00:00','2016-12-21 00:00:00','2016-12-21 18:47:12',10982,343633967,111222333,'First')
,('2016-12-01 00:00:00','2016-12-22 00:00:00','2016-12-22 15:53:59',17820,343885389,111222333,'Repeat')
,('2016-12-01 00:00:00','2016-12-28 00:00:00','2016-12-28 13:07:19',15976,344944219,111222333,'Repeat')
,('2016-12-01 00:00:00','2016-12-29 00:00:00','2016-12-29 21:35:44',17896,345396945,111222333,'Repeat')
,('2016-12-01 00:00:00','2016-12-29 00:00:00','2016-12-29 21:46:43',15498,345398005,111222333,'Repeat')
,('2017-01-01 00:00:00','2017-01-02 00:00:00','2017-01-02 16:24:12',13117,346045147,111222333,'Repeat')

【问题讨论】:

您能提供创建表和插入值吗? 不知道 CTE 的情况,但我肯定会在你的未来看到自我加入。你能提供模式和行构造函数吗? @McNets 当然是人,刚刚编辑了添加一些 SQL 的问题。 您想将重复调用添加为新列,是吗? 这需要 CLR 解决方案。用 C# 编写一个小函数,迭代每个调用者的调用,定义它是否在上次调用的定义时间跨度内,从而计算重复调用以及受影响的员工。您可以使用 .net DataTable 创建结果集并根据需要输出它 - 我更喜欢 sql 管道。陡峭的学习曲线,但值得。 【参考方案1】:

如果我了解您的问题,您想知道每次通话的内容,7 天内重复了多少次通话。

SELECT
  a.date_time
  ,a.emp_id
  ,a.phone_no
  ,count(b.phone_no) as repeat_calls  --count any non-null field
  ,min(b.date_time) as first_repeat_call_at
FROM t_calls a
LEFT JOIN t_calls b
  ON a.phone_no = b.phone_no  --same phone
    AND datediff(d, a.date_time, b.date_time) between 0 AND 6 --a repeat comes in today + 6 days
    AND a.date_time < b.date_time  --prevents self join
GROUP BY
  a.date_time
  ,a.emp_id
  ,a.phone_no

对于任何重复次数为 0 的呼叫,都不会加入任何内容,因此无需计算任何内容,因此 repeat_calls = 0 和 first_repeat_call_at 为 NULL。

【讨论】:

以上是关于每行之间具有固定时间跨度的 SQL 连续行的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询 - 计算值大于 X 的连续行数

pandas:将具有相同值的连续行分组为一组

计算每天 Ms-Sql 总行中的最大连续行

差距和岛屿 - 如何按 ID 对每组连续行求和

如何计算非连续行之间经过的时间?

聚合 SQL 中的连续行