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

How to select many database rows using custom rule?

我目前有一个很大的 table(数百万行),其中包含两列:时间戳(毫秒)和值。

我希望能够以固定时间增量使用仪器的最新值在 PHP 中生成 CSV 文件。举个例子:

Table: data

timestamp  value
50         1
700        2
1500       3
2100       4
3100       5
3900       6

假设固定时间增量为 1 秒(1000 毫秒),输出应如下所示:

timestamp  value
1000       2
2000       3
3000       4
4000       6

我目前正在发出以下形式的许多查询:

SELECT * FROM `data` WHERE timestamp<=2000 ORDER BY `timestamp` DESC LIMIT 1

然后我将每一行输出到 php://output,用户的浏览器会在文件创建时下载它。然而,考虑到所有查询,这种首先生成数据的方法被证明过于缓慢。

我怎样才能加快这个过程?我想我可能应该将大部分处理移动到 MySQL 以减少进程间通信,但我不确定该怎么做。

我不知道这会有多高效,因为数学和没有索引,但您可以使用这样的查询:

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

这里有演示 fiddle:http://sqlfiddle.com/#!9/5a199/13

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

您希望最大时间戳的值等于或小于增量 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

您也可以将每个时间戳四舍五入,然后得到每个四舍五入结果的最大时间戳。

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