GROUP BY成为固定大小的块(使用MySQL)

时间:2017-11-03 07:20:14

标签: mysql

我有来自传感器的累积数据的MySQL DB,我想在一定间隔内计算传感器的最大值。

这是数据片段:

"id",  "dateCreate",           "temp"
"2",   "2017-08-19 03:19:08",  "24.63"
"3",   "2017-08-19 03:24:11",  "24.65"
"14",  "2017-08-19 03:29:15",  "24.63"
"15",  "2017-08-19 03:38:49",  "24.63"
"26",  "2017-08-19 03:43:53",  "24.56"
"37",  "2017-08-19 03:48:55",  "24.60"
"38",  "2017-08-19 03:53:59",  "24.65"
"49",  "2017-08-19 03:59:01",  "24.70"
"50",  "2017-08-19 04:04:04",  "24.75"
"51",  "2017-08-19 04:09:07",  "24.70"
"62",  "2017-08-19 04:14:07",  "24.70"

我想将这些数据分组为N(大小可能不同)行的块,并在每个块上运行MAX(或MIN)。

如果我将样本数据分组为3行,预期结果将是:

"id",  "dateCreate",           "temp"
"3",   "2017-08-19 03:24:11",  "24.65"
"15",  "2017-08-19 03:38:49",  "24.63"
"50",  "2017-08-19 04:04:04",  "24.75"
"51",  "2017-08-19 04:09:07",  "24.70"

我花了几个小时寻找解决方案,但遗憾的是无法找到任何有效的方法。

我认为解决方案可能基于在子查询中使用行编号和/或限制行(具有偏移)的技术,但我设法创建的测试查询看起来很糟糕并且没有按预期工作(此外他们太慢了。)

以下是一个在一个时间间隔内获得最大值的示例:

SELECT a.*
     FROM (
           SELECT *
             FROM MultiTemp
            ORDER BY dateCreate DESC
            LIMIT 100 -- OFFSET is needed
          ) AS a
 INNER JOIN (
   SELECT MAX(temp) AS temp
     FROM (
           SELECT *
             FROM MultiTemp
            ORDER BY dateCreate DESC
            LIMIT 100 -- OFFSET is needed
          ) AS L
 ) AS M
 ON a.temp = M.temp

使用PHP进行进一步的数据处理(生成图形),因此上面提到的通用查询我可以为其他区间配备OFFSET。不幸的是它太慢了......

到目前为止,问题主要集中在分组上:选择其他数据字段可以使用提议的here等方法实现。

我相信这样的任务(组成固定大小的组)对于引擎来说要比按某些列分组要容易得多,所以我可能忽略了一些事情......

更新1 :列id包含自动递增的值,但不保证它是连续的 - 该表保存来自不同设备的数据,我想要分组一个设备(为了简洁起见,我将此方面排除在范围之外)。我调整了样本数据。抱歉混淆!

1 个答案:

答案 0 :(得分:0)

让我们试试这个:

SET @chunk = 3;
SET @serial = @chunk - 1;
SELECT *
FROM (
    SELECT (@serial := @serial+1) DIV @chunk AS `serial_number`,
           `MultiTemp`.*
    FROM `MultiTemp`
    ORDER BY `serial_number`, `temp` DESC
) x
GROUP BY `serial_number`

您可以从上一个结果中删除临时字段serial_number

如需提高价格,您可以尝试:

SET @chunk = 3;
SET @serial = @chunk - 1;
SELECT *
FROM (
    SELECT (@serial := @serial+1) DIV @chunk AS `serial_number`,
           `y`.*
    FROM (
        SELECT *
        FROM `MultiTemp`
        LIMIT 99
    ) y
    ORDER BY `serial_number`, `temp` DESC
) x
GROUP BY `serial_number`