Search code examples
sqlitesumsequence

SQLITE Summary by Sequence


I have a table where name, start time and duration.
I need a query that will give me the last 5 names, start time and duration. When if there is a sequence of several names - should get the beginning of the sequence, and its overall continuation.
If there are several sequences of the same name - should only get the last one.

for example:

name start_time duration
a 79431 70
a 79420 11
a 79415 5
b 79413 1
c 79300 112
c 79298 2
b 79296 2
c 79288 6
c 79284 3
c 79278 347
d 78400 200
d 77764 636
e 77759 4
d 77741 17
f 77700 7
a 77642 10

Should be:

name seq start_time seq duration seq
a 79415 86
b 79413 1
c 79298 114
d 77764 836
e 77759 4

Would appreciate help! Thank you


Solution

  • You need to definir when we start a new sequence with the same name.
    I have 2 queries, one takes all occurences of a name as one sequence. The other keeps them together if they follow in the table.

    create table table_name(
    name varchar(10),
    start_time int,
    duration int);
    
    insert into table_name values
    ('a',79431,70),
    ('a',79420,11),
    ('a',79415,5),
    ('b',79413,1),
    ('c',79300,112),
    ('c',79298,2),
    ('b',79296,2),
    ('c',79288,6),
    ('c',79284,3),
    ('c',79278,347),
    ('d',78400,200),
    ('d',77764,636),
    ('e',77759,4),
    ('d',77741,17),
    ('f',77700,7),
    ('a',77642,10);
    
    select
      t.name,
      min(start_time) beginning,
      sum(duration) duration
    from table_name t
    join
    (select distinct name
    from table_name
    order by start_time desc
    limit 5) n
    on t.name = n.name
    group by t.name;
    
    name | beginning | duration
    :--- | --------: | -------:
    a    |     77642 |       96
    b    |     79296 |        3
    c    |     79278 |      470
    d    |     77741 |      853
    e    |     77759 |        4
    
    select
    name,
    min(start_time) beginning,
    sum(duration) duration
    from
    (select 
      name,
      start_time,
      duration,
      row_number() over(order by start_time) rn,
      row_number() over(order by start_time desc)
       - row_number() over(partition by name order by start_time desc) as group_number
    from table_name) t
    group by name,group_number
    order by group_number
    limit 5;
    
    name | beginning | duration
    :--- | --------: | -------:
    a    |     79415 |       86
    b    |     79413 |        1
    c    |     79298 |      114
    b    |     79296 |        2
    c    |     79278 |      356
    

    db<>fiddle here