我目前有一个包含两列的大表(数百万行):timestamp(ms)和value。
我希望能够使用固定时间增量的仪器的最新值在PHP中生成CSV文件。举个例子:
Table: data
timestamp value
50 1
700 2
1500 3
2100 4
3100 5
3900 6
假设固定时间增量为1秒(1000 ms),输出应如下所示:
timestamp value
1000 2
2000 3
3000 4
4000 6
我目前正在发出以下形式的许多查询:
SELECT * FROM `data` WHERE timestamp<=2000 ORDER BY `timestamp` DESC LIMIT 1
然后我将每一行输出到php://输出,用户的浏览器会在创建文件时下载该文件。但是,考虑到所有查询,这种首先生成数据的方法变得过慢。
如何加快这个过程?我假设我应该将大部分处理工作转移到MySQL以减少进程间通信,但我不确定如何去做。
答案 0 :(得分:3)
您希望最大时间戳上的值等于或小于增量1000的倍数。您可以自动化您的流程:
select 1000 * ceil(lt.timestamp / 1000) as timestamp, value
from data lt
where not exists (select 1
from data lt2
where lt2.timestamp > lt.timestamp and
lt2.timestamp <= 1000 * ceil(lt.timestamp / 1000)
);
data(timestamp)
上的索引应该会有所帮助。
你无法在MySQL中完成你的表达,因为MySQL在这些类型的子查询中不支持limit
。
答案 1 :(得分:2)
您还可以对每个时间戳进行舍入,然后获得每个舍入结果的最大TimeStamp。
SELECT
a.RoundedTimeStamp,
t.Value
FROM(SELECT
CEIL(TimeStamp/1000)*1000 as RoundedTimeStamp,
MAX(TimeStamp) as TimeStamp
FROM tablename
GROUP BY CEIL(TimeStamp/1000)*1000
) a
JOIN tablename t
ON t.TimeStamp = a.TimeStamp
答案 2 :(得分:1)
我不知道这将是多么高效,因为数学和没有索引,但你可以使用这样的查询:
select q1.nearest, q1.value
from
(select t,
if(mod(t, 1000), (floor(t/1000) + 1) * 1000, t) nearest,
if(mod(t, 1000), (floor(t/1000) + 1) * 1000, t) -t as diff,
value
from data
) q1
left join
(select t,
if(mod(t, 1000), (floor(t/1000) + 1) * 1000, t) nearest,
if(mod(t, 1000), (floor(t/1000) + 1) * 1000, t) -t as diff,
value
from data
) q2
on q1.nearest = q2.nearest
and q1.diff > q2.diff
where q2.diff is null
这里有演示小提琴:http://sqlfiddle.com/#!9/5a199/13
请注意,假设没有两个时间戳相同。