【问题标题】:How to count when value crosses the average当价值超过平均值时如何计算
【发布时间】:2019-01-02 23:09:47
【问题描述】:

我正在尝试编写一个 MySQL 查询来计算一个值与常量交叉的次数。最终结果是我们通过值的幅度和频率来确定值的相对“噪声”。 MIN() 和 MAX() 提供幅度。 Count() 给出符合标准的样本数,但它不提供该值的稳定性。我们目前正在使用 MySQL 5.7,但我们将迁移到提供窗口功能的 MySQL 8.0。像

Select Count(Value) over (order by logtime ROWS 1 Proeeding <123 AND 1 Following > 123) WHERE logtime BETWEEN...;

感谢您提供的任何帮助。

SELECT Count(Value) WHERE Value > 123 AND logtime BETWEEN...;

SELECT Count(Value) WHERE Value < 123 AND logtime BETWEEN...;

【问题讨论】:

  • 请提供示例数据和预期结果。
  • 您想计算相邻行的数量,其中第一个低于平均水平,第二个高于平均水平,反之亦然。该描述是否有助于您找到算法?

标签: mysql count average


【解决方案1】:

8.0 之前的 MySQL 版本不支持窗口函数

在 MySQL 5.7 中,我们可以通过在精心设计的查询中使用用户定义的变量来模拟一些窗口函数。 MySQL 参考手册给出了关于在这样的上下文中使用用户定义变量的明确警告。我们依赖于无法保证的行为。

但作为一个示例,我将使用该模式来实现指定的结果:

SELECT SUM(c.crossed_avg) AS count_crossed_avg
  FROM ( 
         SELECT IF( ( @prval > a.avg_ AND t.value < a.avg_ ) OR 
                    ( @prval < a.avg_ AND t.value > a.avg_ )
                ,1,0) AS crossed_avg
              , @prval := t.value AS value_
           FROM mytable t
          CROSS
           JOIN ( SELECT 123 AS avg_ ) a
          CROSS
           JOIN ( SELECT @prval := NULL ) i
          WHERE ...
          ORDER BY t.logtime

       ) c

要解压,首先关注内联视图查询;也就是说,忽略 SELECT SUM() 包装查询,只运行内联视图查询。

我们按logtime 对行进行排序,以便我们可以按顺序处理行。

我们将当前行的值与前一行的值进行比较。如果一个高于平均水平,另一个低于平均水平,则返回 1,否则返回 0。

将当前值保存到用户定义的变量中,用于比较下一行。 (注意:操作的顺序很重要;我们依靠 MySQL 在评估IF() 函数之后执行该分配。


当行值完全等于平均值​​时,示例查询没有解决边缘情况,例如一系列值124.4 123.0 122.2。 (我们可能需要考虑更改比较,以便包含相等性,例如 &lt;&gt;=

【讨论】:

  • 谢谢。我会试试看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
  • 2012-06-19
相关资源
最近更新 更多