Вам нужны аналитические функции LAG
и MIN
.
Они отсутствуют в MySQL
, но их легко эмулировать с помощью переменных сеанса.
Этот запрос возвращает все различия между последовательными записями:
SELECT (temperature - @r) AS diff,
@r := temperature
FROM (
SELECT @r := 0
) vars,
temperatures
ORDER BY
time
Этот возвращает минимальную разницу во времени:
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
)
См. Эту статью в моем блоге о том, как эмулировать аналитические функции в MySQL
:
Если вы добавите PRIMARY KEY
к себе в таблицу (что вы всегда должны делать, всегда делайте!), То вы можете использовать более SQL
-ish решение:
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
Это решение, однако, весьма неэффективно в MySQL
из-за ошибки 20111 .
Подзапрос не будет использовать путь доступа range
, хотя он будет использовать индекс для (timestamp
, id
) для упорядочения.
Это можно обойти, создав UDF
, который возвращает предыдущую температуру, учитывая текущую запись id
.
См. Эту статью в моем блоге для деталей:
Если вы не используете какие-либо условия фильтрации, то решение, использующее переменную сеанса, будет наиболее эффективным, хотя и MySQL
специфичным.
Подобные решения для SQL Server
будут выглядеть так:
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
и
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
В SQL Server
это будет работать нормально, если у вас есть индекс на (timestamp, id)
(или просто на (timestamp)
, если ваш PRIMARY KEY
кластеризован)