What you need is analytical functions LAG
and MIN
.
They are missing in MySQL
, but can be easily emulated using session variables.
This query returns all differences between consecutive records:
SELECT (temperature - @r) AS diff,
@r := temperature
FROM (
SELECT @r := 0
) vars,
temperatures
ORDER BY
time
This one returns minimal time difference:
SELECT (
SELECT id,
@m := LEAST(@m, TIMEDIFF(time, @r)) AS mindiff,
@r := time
FROM (
SELECT @m := INTERVAL 100 YEAR,
@r := NULL
) vars,
temperatures
ORDER BY
time, id
) qo
WHERE qo.id =
(
SELECT id
FROM temperatures
ORDER BY
time DESC, id DESC
LIMIT 1
)
See this article in my blog on how to emulate analytic functions in MySQL
:
If you add a PRIMARY KEY
to you table (which you should always, always do!), then you may use more SQL
-ish solution:
SELECT temperature -
(
SELECT temperature
FROM temperatures ti
WHERE (ti.timestamp, ti.id) < (to.timestamp, to.id)
ORDER BY
ti.timestamp DESC, ti.id DESC
LIMIT 1
)
FROM temperatures to
ORDER BY
to.timestamp, to.id
This solution, though, is quite inefficient in MySQL
due to the bug 20111.
The subquery will not use the range
access path, though it will use an index on (timestamp
, id
) for ordering.
This may be worked around by creating a UDF
that returns previous temperature, given the current record's id
.
See this article in my blog for details:
IF you don't use any filtering conditions, then the solution which uses session variable will be the most efficient, though MySQL
specific.
Similar solutions for SQL Server
will look like this:
SELECT temperature -
(
SELECT TOP 1 temperature
FROM temperatures ti
WHERE ti.timestamp < to.timestamp
OR (ti.timestamp = to.timestamp AND ti.id < to.id)
ORDER BY
ti.timestamp DESC, ti.id DESC
)
FROM temperatures to
ORDER BY
to.timestamp, to.id
and
SELECT MIN(mindiff)
FROM (
SELECT timestamp -
(
SELECT TOP 1 timestamp
FROM temperatures ti
WHERE ti.timestamp < to.timestamp
OR (ti.timestamp = to.timestamp AND ti.id < to.id)
ORDER BY
ti.timestamp DESC, ti.id DESC
) AS mindiff
FROM temperatures to
ORDER BY
to.timestamp, to.id
) q
In SQL Server
, this will work OK, provided you have an index on (timestamp, id)
(or just on (timestamp)
, if your PRIMARY KEY
is clustered)