【问题标题】:Average of successive pairs of rows连续对行的平均值
【发布时间】:2018-09-17 16:03:47
【问题描述】:

我有一张这样的桌子:

id | value
---+------
1  |  10
2  |  5
3  |  11
4  |  8
5  |  9
6  |  7

此表中的数据实际上是成对的值,我需要对其取平均值,结果应该是:

pair_id | pair_avg
--------+---------
1       | 7.5
2       | 9.5
3       | 8

我有一些其他信息(一对标志)也可以帮助它们配对,尽管它们仍然必须按 id 顺序排列。我无法真正改变数据的来源。

由于我更习惯于使用数组而不是 SQL,我所能想到的就是我需要遍历表并对这些对求和。但这并没有让我觉得非常 SQL 风格。

更新

在制作这个最小的例子时,我显然过于简化了。 由于我正在使用的表是多次选择的结果,因此 ID 不会那么干净,很抱歉没有指定这一点。

表格看起来更像:

id | value
----------
1  | 10
4  | 5
6  | 11
7  | 8
10 | 9
15 | 7

结果将用于创建第二个表,我不关心这个新表上的索引,它可以提供自己的,因此给出上面已经指出的结果。

【问题讨论】:

    标签: sql postgresql aggregate


    【解决方案1】:

    如果您的数据与问题看起来一样干净:没有 NULL 值,没有间隙,对有连续的正数,从 1 开始,假设 id 是类型 integer ,它可以很简单:

    SELECT (id+1)/2 AS pair_id, avg(value) AS pair_avg
    FROM   tbl
    GROUP  BY 1
    ORDER  BY 1;
    

    Integer division 会截断结果,从而以这种方式自动处理分组对。

    如果您的 id 号码不像您的 update 建议的那样常规但至少 strictly monotonically increasing(仍然没有 NULL 或缺失值),您可以使用代理 ID使用row_number() 生成:

    SELECT id/2 AS pair_id, avg(value) AS pair_avg
    FROM   (SELECT row_number() OVER (ORDER BY id) + 1 AS id, value FROM tbl) t
    GROUP  BY 1
    ORDER  BY 1;

    db小提琴here

    【讨论】:

    • 谢谢你,不幸的是我的最小例子太小了。我已经用更多信息更新了这个问题。
    • @RDavies:我添加了第二个解决方案来涵盖您的更新。
    【解决方案2】:

    我认为您可以将 group by 与算术一起使用:

    select row_number() over (order by min(id)), min(id), max(id), avg(id)
    from t
    group by floor( (id - 1) / 2 );
    

    我不确定您为什么要在聚合后重新编号 ID。原来的 id 似乎更有用。

    【讨论】:

      【解决方案3】:

      您可以通过将除以 2 应用到 id 列来实现 use ceil 函数,如下面的 select 语句:

      with t(id,value) as
      (
       select 1  ,  10  union all
       select 2  ,  5   union all
       select 3  ,  11  union all
       select 4  ,  8   union all
       select 5  ,  9   union all
       select 6  ,  7    
      )
      select ceil(id/2::numeric) as "ID", avg(t.value) as "pair_avg"
        from t
       group by "ID"
       order by "ID";
      
      
      id | pair_avg
      -------------
      1  | 7.5
      2  | 9.5
      3  | 8
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-29
        • 2020-10-15
        • 1970-01-01
        • 2012-04-11
        • 1970-01-01
        • 2022-01-22
        相关资源
        最近更新 更多