Несколько перекрывающихся дат в нескольких строках T SQL необходимо сократить до итоговой строки - PullRequest
0 голосов
/ 04 мая 2020

У меня есть ситуация, когда наша система создает несколько перекрывающихся строк для активности входа в систему конечными пользователями в системе. Я понятия не имею, почему он это делает, но это так. Я добавлю несколько строк в качестве примера ниже:

 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 последней строки. Я пытался понять, как к этому подойти, и пробовал несколько подходов, но ни один из них не увенчался успехом. Кто-нибудь знает, как я могу этого добиться?

Заранее благодарен за любую помощь.

1 Ответ

1 голос
/ 05 мая 2020

Это проблема промежутков и островов. Вот один из подходов, который использует 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
...