The code below does what I need, but I don't understand why, hence I don't understand if it is reliable/correct.
I am trying to calculate the duration of each Action. Each action has the starting time marked by the action name in the Action column and the ending time marked by the word 'Done'. Two actions can overlap in time if they have different users, but not with the same user.
I wanted to search for each Action = 'Done'
and the record with the same user and the highest time before that one. I tried to use Max()
in different positions to find the highest Start.Time
such that Start.Time < End.Time
, but it never worked. I tried with Max() in a subquery, but the Start
in the subquery and the Start
in the Join
were not the same. So I removed Max()
and I got what I was looking for.
Why are the Start and End records matching correctly instead of for example matching the first and the last record of each user?
Does it reliably always pick the last record of the group according to the Order by
clause? Or was I just lucky?
Here is the code that creates the table, inserts some test data and does the query:
CREATE TABLE Log (
Time DATETIME,
User CHAR,
[Action] CHAR
);
insert into Log values('2017-01-01 10:00:00', 'Joe', 'Play');
insert into Log values('2017-01-01 10:01:00', 'Joe', 'Done');
insert into Log values('2017-01-01 10:02:00', 'Joe', 'Sing');
insert into Log values('2017-01-01 10:03:00', 'Joe', 'Done');
insert into Log values('2017-01-01 10:04:00', 'Ann', 'Play');
insert into Log values('2017-01-01 10:05:00', 'Joe', 'Play');
insert into Log values('2017-01-01 10:06:00', 'Ann', 'Done');
insert into Log values('2017-01-01 10:07:00', 'Joe', 'Done');
insert into Log values('2017-01-01 10:08:00', 'Ann', 'Play');
insert into Log values('2017-01-01 10:09:00', 'Ann', 'Done');
SELECT Start.*,
[End].*,
strftime('%s', [End].Time) - strftime('%s', Start.Time) AS Duration
FROM Log AS Start
JOIN
Log AS [End] ON Start.User = [End].User AND
Start.Time < [End].Time
WHERE [End].[Action] = 'Done'
GROUP BY [End].Time
ORDER BY Duration DESC,
Start.Time;