多个 TSQL 行中的多个重叠日期需要减少为汇总行
Posted
技术标签:
【中文标题】多个 TSQL 行中的多个重叠日期需要减少为汇总行【英文标题】:Multiple Overlapping dates in multiple TSQL Rows needs to be reduced to a summary row 【发布时间】:2020-05-04 20:46:08 【问题描述】:我遇到的情况是,我们的系统为系统上的最终用户的登录活动创建了多个重叠行。我不知道它为什么这样做,但确实如此。我将在下面添加几行作为示例:
RN2 UserRegistryID LoginTime LogoutTime FinalLoginTime FinalLogoutTime
-------------------- -------------- ----------------------- ----------------------- -------------- ---------------
1 x89889 2018-05-15 12:56:30.000 2018-05-15 13:08:24.873
2 x89889 2018-06-26 09:08:59.000 2018-06-26 09:22:24.003
3 x89889 2018-06-26 09:22:58.000 2018-06-26 09:51:02.057
4 x89889 2018-11-09 12:50:58.000 2018-11-09 13:33:56.250
5 x89889 2019-02-12 13:16:17.000 2019-02-12 13:18:39.293
6 x89889 2019-02-12 13:19:38.000 2019-02-12 13:38:02.627
7 x89889 2019-02-19 13:52:00.000 2019-02-19 14:22:18.000
8 x89889 2019-02-19 14:23:34.000 2019-02-19 15:24:02.000
9 x89889 2019-03-03 13:20:52.000 2019-03-03 13:29:50.000
10 x89889 2019-03-03 13:30:25.000 2019-03-03 15:55:02.247
11 x89889 2019-06-21 12:19:35.000 2019-06-21 12:34:01.103
12 x89889 2019-09-17 07:55:06.000 2019-09-17 09:08:26.007
13 x89889 2019-09-19 20:22:40.000 2019-09-19 20:23:01.723
14 x89889 2019-09-21 23:21:43.000 2019-09-22 00:50:10.867
15 x89889 2019-09-23 00:16:50.000 2019-09-23 00:55:35.183
16 x89889 2019-10-13 22:35:43.000 2019-10-13 23:21:34.000
17 x89889 2019-10-13 23:16:29.000 2019-10-14 00:18:55.000
18 x89889 2019-10-14 00:16:09.000 2019-10-14 00:47:25.003
19 x89889 2019-10-14 12:24:24.000 2019-10-14 12:45:19.000
20 x89889 2020-01-07 15:07:42.000 2020-01-07 15:28:49.093
21 x89889 2020-01-29 14:29:41.000 2020-01-29 15:05:08.223
22 x89889 2020-02-10 12:31:04.000 2020-02-10 12:37:36.343
23 x89889 2020-03-17 19:10:31.000 2020-03-17 19:52:37.003
24 x89889 2020-03-24 15:23:47.000 2020-03-24 15:54:15.000
25 x89889 2020-03-24 16:31:42.000 2020-03-24 16:46:56.000
26 x89889 2020-03-25 21:04:43.000 2020-03-25 21:27:11.000
27 x89889 2020-03-25 21:45:56.000 2020-03-25 22:50:19.003
28 x89889 2020-03-26 01:39:16.000 2020-03-27 09:30:09.003
29 x89889 2020-03-26 18:15:36.000 2020-03-26 18:35:50.000
30 x89889 2020-04-09 18:47:32.000 2020-04-09 19:06:02.000
31 x89889 2020-04-16 19:13:57.000 2020-04-16 20:02:04.000
32 x89889 2020-04-24 09:13:07.000 2020-04-24 09:33:16.000
因此,RN2 列按照这些事件发生的顺序对这些事件进行排序,并且该序列对每个用户进行分区和递增 - 由 UserRegistryID 定义。如您所见,第二行的登录时间在第一行的注销时间之前。第三行也是如此。所以通过查看这个,你可以推断这应该被识别为一个“会话”,从第一行的 LoginTime 和最后一行的 LogoutTime 开始。我一直在试图弄清楚如何解决这个问题,并尝试了多种方法,但都没有成功。有谁知道我如何实现这一目标?
非常感谢您提前提供的任何帮助。
【问题讨论】:
这似乎是空白和孤岛问题。你试过什么?为什么它不起作用?向我们展示您的实际预期结果,并向我们提供我们可以使用的示例数据(不是图片)也将有助于我们为您提供帮助。 @Larnu 这有帮助吗? 【参考方案1】:这是一个孤岛问题。这是一种使用lag()
和累积sum()
定义连续重叠行组的方法,然后您可以聚合:
select
userRegistryID,
min(rn2) min_rn2,
max(rn2) max_rn2,
min(loginTime) minLoginTime,
max(logoutTime) maxLogoutTime,
count(*) no_records
from (
select
t.*,
sum(case when loginTime <= lagLogoutTime then 0 else 1 end)
over(partition by userRegistryID order by rn2) grp
from (
select
t.*,
lag(logoutTime) over(partition by userRegistryID order by rn2) lagLogoutTime
from mytable t
) t
) t
group by userRegistryID, grp
order by userRegistryID, minLoginTime
或者,如果您不想聚合行,而是将每个会话的开始和结束日期添加到每一行,您可以这样做:
select
rn2,
userRegistryID,
loginTime,
logoutTime,
min(loginTime) over(partition by userRegistryID, grp) finalLoginTime,
max(logoutTime) over(partition by userRegistryID, grp) finalLogoutTime
from (
select
t.*,
sum(case when loginTime <= lagLogoutTime then 0 else 1 end)
over(partition by userRegistryID order by rn2) grp
from (
select
t.*,
lag(logoutTime) over(partition by userRegistryID order by rn2) lagLogoutTime
from mytable t
) t
) t
order by userRegistryID, rn2
【讨论】:
嗨@GMB 谢谢你。与此有关的一个问题,也是我没有澄清的错是同一用户的其他行将是不同的会话。我将在附加评论中添加所有数据。为了回答您的问题,我想保留这些行,但只在最后两列中添加最终会话登录和注销时间。 @Larnu - 我希望这会有所帮助,我已将原始问题更新为包含文本而不是图像。我最初尝试了查看上一行和下一行并标记它们的 fw 组合,但那是在我意识到你可以有很多行之前,这是真的。我认为答案可能在于嵌套的while循环,但是1,我没时间了,2,我没那么聪明!以上是关于多个 TSQL 行中的多个重叠日期需要减少为汇总行的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 或 MariaDB 将单行中的日期范围分散到多个行中