Reputation: 510
I am looking to extend the accepted answer here:
SQL Server find datediff between different rows, sum
Extended Data Set:
ID | Time |OnOffSite| UserName | Reason
------------------------------------------------------
123 | 2011-10-25 09:00:00.000 | on | Bloggs Joe | NULL
124 | 2011-10-25 12:00:00.000 | off | Bloggs Joe | Shift
125 | 2011-10-25 13:00:00.000 | on | Bloggs Joe | NULL
126 | 2011-10-25 17:00:00.000 | off | Bloggs Joe | Travel
127 | 2011-10-25 09:00:00.000 | on | Jonesy Ian | NULL
128 | 2011-10-25 10:00:00.000 | on | Jonesy Ian | NULL
129 | 2011-10-25 11:00:00.000 | off | Jonesy Ian | End Shift
130 | 2011-10-25 12:00:00.000 | on | Jonesy Ian | NULL
131 | 2011-10-25 15:00:00.000 | off | Jonesy Ian | OverTime
I have tried extendeing out the provided answer grouping by the new column with no luck:
-- =====================
-- sample data
-- =====================
declare @t table
(
ID int,
Time datetime,
OnOffSite varchar(3),
UserName varchar(50),
Reason varchar(50)
)
insert into @t values(123, '2011-10-25 09:00:00.000', 'on', 'Bloggs Joe', 'NULL')
insert into @t values(124, '2011-10-25 12:00:00.000', 'off', 'Bloggs Joe', 'Shift')
insert into @t values(125, '2011-10-25 13:00:00.000', 'on', 'Bloggs Joe', 'NULL')
insert into @t values(126, '2011-10-25 17:00:00.000', 'off', 'Bloggs Joe', 'Travel')
insert into @t values(127, '2011-10-25 09:00:00.000', 'on', 'Jonesy Ian', 'NULL')
insert into @t values(128, '2011-10-25 10:00:00.000', 'on', 'Jonesy Ian', 'NULL')
insert into @t values(129, '2011-10-25 11:00:00.000', 'off', 'Jonesy Ian', 'Travel')
insert into @t values(130, '2011-10-25 12:00:00.000', 'on', 'Jonesy Ian', '')
insert into @t values(131, '2011-10-25 15:00:00.000', 'off', 'Jonesy Ian', 'Shift')
-- =====================
-- solution
-- =====================
select
UserName, Reason, diffinhours = DATEDIFF(hh, timeon, timeoff)
from
(
select
UserName,
Reason,
timeon = max(case when k = 2 and OnOffSite = 'on' then Time end),
timeoff = max(case when k = 1 and OnOffSite = 'off' then Time end)
from
(
select
ID,
UserName,
Reason,
OnOffSite,
Time,
rn = ROW_NUMBER() over(partition by username, Reason, order by id)
from
(
select
ID,
UserName,
Reason,
OnOffSite,
Time,
rn2 = case OnOffSite
-- '(..order by id)' takes earliest 'on' in the sequence of 'on's
-- to take the latest use '(...order by id desc)'
when 'on' then
ROW_NUMBER() over(partition by UserName, Reason, OnOffSite, rn1 order by id)
-- '(... order by id desc)' takes the latest 'off' in the sequence of 'off's
-- to take the earliest use '(...order by id)'
when 'off' then
ROW_NUMBER() over(partition by UserName, Reason, OnOffSite, rn1 order by id desc)
end,
rn1
from
(
select
*,
rn1 = ROW_NUMBER() over(partition by username, Reason, order by id) +
ROW_NUMBER() over(partition by username, Reason, onoffsite order by id desc)
from @t
) t
) t
where rn2 = 1
) t1
cross join
(
select k = 1 union select k = 2
) t2
group by UserName, Reason, rn + k
) t
where timeon is not null or timeoff is not null
order by username
I am only logging an a reason when OnOffSite = "off". I believe the problem is the value of Reason is NULL when OnOffSite = "on" but in this case I only want to group by the timestamp and use the "off" Reason as the value.
This is SQL Server 2012
Upvotes: 1
Views: 75
Reputation: 169
Remove the Reason
from the grouping and replace line 32's Reason
with reason = max(case when OnOffSite = 'on' then null else Reason end)
so that the code looks something like this:
[...................................]
-- =====================
-- solution
-- =====================
select
UserName, timeon, timeoff, diffinhours = DATEDIFF(hh, timeon, timeoff), reason
from
(
select
UserName,
reason = max(case when OnOffSite = 'on' then null else Reason end),
timeon = max(case when k = 2 and OnOffSite = 'on' then Time end),
timeoff = max(case when k = 1 and OnOffSite = 'off' then Time end)
from
(
select
ID,
UserName,
OnOffSite,
Time,
rn = ROW_NUMBER() over(partition by username order by id),
Reason
[...................................]
It's not exactly by-the-book to use max with strings but it should work for this case.
Upvotes: 1