I have a table with 2 fields: unique ID, user ID (foreign key) and date-time. This is an access-log to a service. I work in SQL Server but I would appreciate agnostic answer
Very similar to RichardTallent's answer...
SELECT
t1.id,
t1.[user-id],
t1.time,
DATEDIFF(s, t1.time, t2.time) AS GapTime
FROM
t AS t1
INNER JOIN
t AS t2
ON t2.[user-id] = t1.[user-id]
AND t2.time = (
SELECT
MIN(time)
FROM
t
WHERE
[user-id] = t1.[user-id]
AND time > t1.time
)
AS you are only actually using the time value from t2, you can actually re-organise as follows to deal with users with just one entry...
SELECT
t1.id,
t1.[user-id],
t1.time,
DATEDIFF(
s,
t1.time,
(
SELECT
MIN(time)
FROM
t
WHERE
[user-id] = t1.[user-id]
AND time > t1.time
)
) AS GapTime
FROM
t1
Finally, there is the possiblity of multiple entries with the same time stamp. When that happens we need additional info to decide the order allowing us to determine which record is 'next'.
Where there are several entries with the same time stamp, all bar one will have a GapTime of 0:
- '12:00' (Gap of 1 until next entry)
- '12:01' (Gap of 0 until next entry)
- '12:01' (Gap of 0 until next entry)
- '12:01' (Gap of 0 until next entry)
- '12:01' (Gap of 1 until next entry)
- '12:02' (Gap of NULL until next entry)
Only the one which is 'last' will have a non-zero time stamp. Although the question states that the "id" may not be in order, it is the only info we have for to determine which reocrd is 'last' when the timestamps are the same.
SELECT
t1.id,
t1.[user-id],
t1.time,
DATEDIFF(
s,
t1.time,
(
SELECT
MIN(time)
FROM
t
WHERE
[user-id] = t1.[user-id]
AND
(
(time > t1.time)
OR
(time = t1.time AND id > t1.id)
)
)
) AS GapTime
FROM
t1