多个TSQL行中的多个重叠日期需要减少为摘要行

问题描述 投票:0回答:1

我遇到这样的情况,我们的系统为系统上的最终用户创建了多个重叠的行用于登录活动。我不知道为什么会这样做,但确实如此。我将在下面添加一些行作为示例:

 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开始。我一直在尝试找出解决方法,并尝试了许多方法,但都没有成功。有谁知道我将如何实现这一目标?

非常感谢您提前提供帮助。

sql-server tsql date group-by gaps-and-islands
1个回答
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
© www.soinside.com 2019 - 2024. All rights reserved.