【问题标题】:MySQL - get min/max of consecutive events in a series of rowsMySQL - 获取一系列行中连续事件的最小/最大值
【发布时间】:2015-11-18 16:12:45
【问题描述】:

我有一张如下所示的表格: http://sqlfiddle.com/#!9/152d2/1/0

CREATE TABLE Table1 (
  id int,
  value decimal(10,5),
  dt datetime, 
  threshold_id int
);

当前查询:

SELECT sensors_id, DATE_FORMAT(datetime, '%Y-%m-%d'), MIN(value), MAX(value) 
FROM Readings 
WHERE datetime < "2015-11-18 00:00:00" 
AND datetime > "2015-10-18 00:00:00" 
AND sensors_id = 9 
GROUP BY DATE_FORMAT(datetime, '%Y-%m-%d') 
ORDER BY datetime DESC

我要做的是返回每个组中的最小值/最大值,其中 threshold_id 不为空。因此,该示例应返回如下内容:

min_value | max_value | start_date          | end_date  
9         | 10.5      | 2015-07-29 10:52:31 | 2015-07-29 10:57:31
8.5       | 9.5       | 2015-07-29 11:03:31 | 2015-07-29 11:05:31

我不知道如何进行此分组。我需要为 threshold_id 不为 NULL 的每组连续行返回最小值/最大值。

【问题讨论】:

  • 您需要指定分组的内容/方式。另外,您的查询目前是什么样的?
  • 我按日期时间分组,我的查询是这样的:SELECT id, DATE_FORMAT(dt, '%Y-%m-%d'), MIN(value), MAX(value) FROM Table1 WHERE dt "2015-10-18 00:00:00" AND id = 9 GROUP BY DATE_FORMAT(dt, '%Y-%m-%d' ) 按 dt DESC 排序
  • 您是按日期时间分组(精确到秒)?
  • 没错,真的是按天分组。

标签: mysql


【解决方案1】:

使用用户变量将现有值与以前的值进行比较,并增加一列您可以用来分组的列,在我的机器上进行了测试。

SELECT MIN(value),MAX(value),MIN(dt),MAX(dt)
FROM (
  SELECT id,value,dt,
    CASE WHEN  COALESCE(threshold_id,'')=@last_ci  THEN @n ELSE @n:=@n+1 END AS g,
    @last_ci := COALESCE(threshold_id,'') As th
  FROM
    Table1, (SELECT @n:=0) r 
  ORDER BY
    id 
) s
WHERE th!=''
GROUP BY
  g

对于 mysql 8,这可以重写如下。使用 CTE 获取不同的序列,并通过它们之间的差异进行 GROUP。

WITH cte as (
SELECT *,
  ROW_NUMBER() OVER (ORDER BY id)as rn,
  ROW_NUMBER() OVER (PARTITION BY threshold_id ORDER BY id)as rnn
  FROM Table1
  ORDER BY id
)
SELECT MIN(value),MAX(value),MIN(dt),MAX(dt) FROM cte WHERE threshold_id IS NOT NULL GROUP BY rn-rnn

MYSQL8

FIDDLE

【讨论】:

  • 感谢此代码!我已经成功地从我自己的项目中实现了我所需要的。但是,使用 MySQL 8 我收到警告:“不推荐在表达式中设置用户变量”。我已经查看了使用 CTE 和 LAG() 函数(替换 @last_ci)的解决方案,但是如果不在表达式中设置 @n,我无法深入了解它......有什么想法吗?
  • 您可能可以在 Mysql 8 中完全忽略用户变量。我编辑了我的答案@HiPierr0t
【解决方案2】:

您的示例数据仅包含一天的价值,因此您只能返回一行(假设您想按天分组):

SELECT DAYOFYEAR(dt) `day`, MIN(`value`) min_value, MAX(`value`) max_value 
FROM Table1 
GROUP BY `day` 
ORDER BY `day` ASC

【讨论】:

  • 抱歉,我在处理数千行时已简化数据。在此示例中,按分钟分组在较小的范围内是相同的。
猜你喜欢
  • 1970-01-01
  • 2020-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 2018-10-14
  • 2019-07-13
相关资源
最近更新 更多