MySQL选择AVG,ORDER BY,GROUP BY&限制

时间:2014-10-17 17:40:15

标签: mysql

波纹管声明不起作用,但我似乎无法弄清楚为什么

select AVG(delay_in_seconds) from A_TABLE ORDER by created_at DESC GROUP BY row_type limit 1000;

我想获得每个row_type最近1000行的平均值。 created_at的类型为DATETIME,row_type的类型为VARCHAR

2 个答案:

答案 0 :(得分:2)

如果你只想要1000个最新的行,不管是row_type,然后得到每个row_type的delay_in_seconds的平均值,这是一个相当简单的查询。例如:

SELECT t.row_type
     , AVG(t.delay_in_seconds)
  FROM (
         SELECT r.row_type
              , r.delay_in_seconds
           FROM A_table r
          ORDER BY r.created_at DESC
          LIMIT 1000
       ) t
 GROUP BY t.row_type

但是,我怀疑这个查询满足指定的要求。 (我知道它不符合我对规范的理解。)

如果我们想要的是每个 row_type的最近1000行的平均值,那么这也是相当简单的......如果我们使用的是支持分析函数的数据库。

不幸的是,MySQL不提供对分析功能的支持。但是可以在MySQL中模拟一个,但语法有点涉及,它依赖于保证的行为。

举个例子:

SELECT s.row_type
     , AVG(s.delay_in_seconds)
  FROM ( 
         SELECT @row_ := IF(@prev_row_type = t.row_type, @row_ + 1, 1) AS row_
              , @prev_row_type := t.row_type AS row_type
              , t.delay_in_seconds
           FROM A_table t
          CROSS
           JOIN (SELECT @prev_row_type := NULL, @row_ := NULL) i
          ORDER BY t.row_type DESC, t.created_at DESC
       ) s
 WHERE s.row_ <= 1000
 GROUP
    BY s.row_type

注意:

内联视图查询对于大型集合来说将是昂贵的。有效的做法是为每一行分配一个行号。 “order by”是按created_at的降序排序行,我们想要的是为最近的行分配值1,下一个最近的2,等等。这个行的编号将是对row_type的每个不同值重复。

为了提高性能,我们需要一个带有前导列(row_type,created_at,delay_seconds)的合适索引,以避免昂贵的“使用filesort”操作。我们至少需要前两列,包括delay_seconds使它成为覆盖索引(查询可以完全从索引中得到满足。)

然后,外部查询针对从视图查询返回的结果集(“派生表”)运行。 WHERE中的谓词过滤掉所有分配行数大于1000的行,其余的是一个直接的GROUP BY和AVG聚合。

LIMIT子句完全没必要。有可能为某些额外的性能增强添加一些额外的谓词...比如,如果我们指定了最近的1000行,但在过去的30或90天内只有create_at呢?

(我不完全确定这会回答OP提出的问题。答案是:是否有可以返回指定结果集的查询,使用AVG聚合和GROUP BYORDER BYLIMIT条款。)

N.B。此查询取决于MySQL用户定义变量的行为,保证。


上面的查询显示了一种方法,但也有另一种方法。可以使用“连接”操作(A_table与A_table)来获取分配的行号(获得比每行“更新”的行数COUNT。但是,大型集合可以产生一个如果我们不小心限制它,那么中间结果是巨大的。

答案 1 :(得分:0)

在语句的最后写下ORDER BY。

SELECT AVG(delay_in_seconds) from A_TABLE GROUP BY row_type ORDER by created_at DESC  limit 1000;

阅读mysql dev网站了解详情。