将每个N值分组

时间:2012-10-27 10:02:51

标签: postgresql group-by aggregation

我在PostgreSQL中有这样的表。我想基于ID(主键)为每16条记录执行像mean和max这样的聚合函数。例如,我必须计算前16个记录和后16个记录的平均值,依此类推。

+-----+-------------
| ID  |  rainfall  |
+-----+----------- |
|  1  |  110.2     |
|  2  |  56.6      |
|  3  |  65.6      |
|  4  |  75.9      |
+-----+------------

2 个答案:

答案 0 :(得分:8)

首先想到的方法是使用row_number()来注释表,然后按16行的块进行分组。

SELECT min(id) as first_id, max(id) AS last_id, avg(rainfall) AS avg_this_16
FROM (
  SELECT id, rainfall, row_number() OVER (order by id) AS n
  FROM the_table
) x(id,rainfall,n)
GROUP BY n/16
ORDER BY n/16;

请注意,这不一定包括最后一组的16个样本。

或者,您可以使用avg()作为窗口函数来计算运行平均值

SELECT id, avg(rainfall) OVER (ORDER BY id ROWS 15 PRECEDING)
FROM the_table;

...可能用行号注释并选择你想要的那些:

SELECT id AS greatest_id_in_group, avg_last_16_inclusive FROM (
  SELECT
    id, 
    avg(rainfall) OVER (ORDER BY id ROWS 15 PRECEDING) AS avg_last_16_inclusive,
    row_number() OVER (ORDER BY id) AS n
  FROM the_table
) x WHERE n % 16 = 0;

这将忽略最后的n< 16个样本,而不是为它们返回一行。

请注意,我假设ID不保证是连续的。如果它们没有间隙,你只需group by id/16并避开窗函数。

答案 1 :(得分:0)

迟到的答案,但无论如何都要参考

因为据说ID是连续的并且没有间隙,所以这会非常直接

SELECT avg(rainfall),string_agg(id::text, ',')
FROM the_table
GROUP BY (id - 1) / 16;

注意(id - 1)将分组从零到15,否则第一组可能会分离

PS:@Craig Ringer在答案结束时给出了一个暗示,但没有发布作为代码

  

请注意,我假设ID并不保证是连续的。如果它们没有间隙,你可以按id / 16分组并避开窗口功能。