如何使用自定义规则选择多个数据库行?

时间:2015-04-21 00:35:29

标签: php mysql sql csv select

我目前有一个包含两列的大表(数百万行):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以减少进程间通信,但我不确定如何去做。

3 个答案:

答案 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

请注意,假设没有两个时间戳相同。