Search code examples
sqlsql-servert-sqlsql-server-2014-express

SQL TSQL for Workers per Hour


I have a log with fingerprint timestamps as follows:

Usr   TimeStamp
-------------------------
 1    2015-07-01 08:01:00
 2    2015-07-01 08:05:00
 3    2015-07-01 08:07:00
 1    2015-07-01 10:05:00
 3    2015-07-01 11:00:00
 1    2015-07-01 12:01:00
 2    2015-07-01 13:03:00
 2    2015-07-01 14:02:00
 1    2015-07-01 16:03:00
 2    2015-07-01 18:04:00

And I wish an output of workers per hour (rounding to nearest hour) The theoretical output should be:

 7:00  0
 8:00  3
 9:00  3
 10:00 2
 11:00 1
 12:00 2
 13:00 1
 14:00 2
 15:00 2
 16:00 1
 17:00 1
 18:00 0
 19:00 0

Can anyone think on how to approach this as SQL or if no other way, through TSQL?

Edit: The timestamps are logins and logouts of the different users. So at 8am 3 users logged in and the same 3 are still working at 9am. One of them leaves at 10am. etc


Solution

  • Here is my final working code:

    create table tsts(id int, dates datetime)
    insert tsts values
    (1 ,   '2015-07-01 08:01:00'),
    (2 ,   '2015-07-01 08:05:00'),
    (3 ,   '2015-07-01 08:07:00'),
    (1 ,   '2015-07-01 10:05:00'),
    (3 ,   '2015-07-01 11:00:00'),
    (1 ,   '2015-07-01 12:01:00'),
    (2 ,   '2015-07-01 13:03:00'),
    (2 ,   '2015-07-01 14:02:00'),
    (1 ,   '2015-07-01 16:03:00'),
    (2 ,   '2015-07-01 18:04:00')
    
    select horas.hora, isnull(sum(math) over(order by horas.hora rows unbounded preceding),0) as Employees from
    
    (
    select 0 as hora union all
    select 1 as hora union all
    select 2 as hora union all
    select 3 as hora union all
    select 4 as hora union all
    select 5 as hora union all
    select 6 as hora union all
    select 7 as hora union all
    select 8 as hora union all
    select 9 as hora union all
    select 10 as hora union all
    select 11 as hora union all
    select 12 as hora union all
    select 13 as hora union all
    select 14 as hora union all
    select 15 as hora union all
    select 16 as hora union all
    select 17 as hora union all
    select 18 as hora union all
    select 19 as hora union all
    select 20 as hora union all
    select 21 as hora union all
    select 22 as hora union all
    select 23
    ) as horas
    
    left outer join 
    (
    select hora, sum(math) as math from 
        (
        select id, hora, iif(rowid%2 = 1,1,-1) math from 
            (
            select row_number() over (partition by id order by id, dates) as rowid, id, datepart(hh,dateadd(mi, 30, dates)) as hora from tsts 
            ) as Q1
        ) as Q2
    group by hora
    ) as Q3 
    
    on horas.hora = Q3.hora
    

    SQL Fiddle