假设我有一个带有时间戳列的表格,我只想用一个查询来计算两个连续记录之间的最小时差。
也许像......这样的表。
CREATE TABLE `temperatures` (
`temperature` double,
`time` timestamp DEFAULT CURRENT_TIMESTAMP
);
答案 0 :(得分:4)
您需要的是分析函数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
由于bug 20111,此解决方案在MySQL
中的效率非常低。
子查询不会使用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
已群集),这将正常运行
答案 1 :(得分:3)
假设时间戳上有一个唯一约束(以防止同时有两个录音):
SELECT MIN(timediff(t1.`time`, t2.`time`)) AS delta_t,
FROM temperatures t1 JOIN temperatures t2 ON t1.`time` < t2.`time`
这相当准确地回答了问题 - 并没有传达其他有用信息(例如哪两个时间戳或温度)。
答案 2 :(得分:2)
尝试这样的查询:
select
cur.timestamp as CurrentTime,
prev.timestamp as PreviousTime,
timediff(cur.timestamp,prev.timestamp) as TimeDifference,
cur.temperature - prev.temperature as TemperatureDifference
from temperatures cur
left join temperatures prev on prev.timestamp < cur.timestamp
left join temperatures inbetween
on prev.timestamp < inbetween.timestamp
and inbetween.timestamp < cur.timestamp
where inbetween.timestamp is null
第一个连接搜索当前(“cur”)行的所有先前行。第二个连接在第一行和第二行之间寻找行。 where语句表示第一行和第二行之间不能有任何行。这样,您将得到一个包含前一行的行列表。
答案 3 :(得分:0)
你可以试试这个:
SELECT
T1.*,
(SELECT MIN(T2.time)
FROM temperatures T2
WHERE T2.time > T1.time)-T1.time diff
FROM
temperatures T1
ORDER BY
T1.time