不精确的 GROUP BY 聚合

问题描述 投票:0回答:2

我正在尝试找出一种方法来推理一个相当简单的问题:

foo
有两列,
id
具有唯一标识符,
value
具有随机
numeric
值。给定一个常数
threshold
值,找到
value
在该阈值内的值组 - 该组的计数以及该组的平均值。

让我们做好准备 - 这是

foo
表(在 PostgreSQL 中):

CREATE TABLE foo (
    id serial PRIMARY KEY,
    value numeric NOT NULL
);

查询应该返回计数和平均值 - 条目不能被重复计算,所以我希望根据某个阈值“接近度”值将行“分成组” - 你可以想到

threshold 
半径值:

SELECT AVG(foo.value), COUNT(foo.id)
  FROM foo
  GROUP BY foo.value; -- where I'm stuck

上面的查询只会将聚合函数应用于其中

foo.value
exact 重复项的行 - 我想要的是类似于以下伪 SQL 的东西:

SELECT AVG(foo.value), COUNT(foo.id)
  FROM foo
  GROUP BY
   (row_being_grouped.value <= foo.value + threshold)
   AND
   (row_being_grouped.value >= foo.value - threshold);

我不确定这是否有意义。我想知道我是否可以在不执行子查询的情况下解决这个问题 - 也许在找到存储桶内的平均值之前以某种方式“存储”行?

sql postgresql group-by aggregate-functions bucket
2个回答
1
投票

如果“阈值”可以理解为同一组值之间允许的最大间隙,那么这是一个明确定义的问题。
解决办法如下:

SELECT grp, count(*) AS grp_count, round(avg(value), 2) AS grp_avg
FROM  (
   SELECT count(gap) OVER (ORDER BY value) AS grp, *
   FROM  (
      SELECT value
           , value - lag(value) OVER (ORDER BY value) > 150 OR null AS gap
      FROM   foo
      ) sub1
   ) sub2
GROUP  BY grp
ORDER  BY grp;

小提琴(带有分步演示)

解释和更多链接:

为了方便和简短的代码,我使用布尔逻辑(

true OR null
true
false OR null
null
),并且
count()
忽略
null
值。参见:

如果这更多的是栅格/集群/粒化/网格问题,您需要准确定义要选择哪些行作为“焦点”,或者独立栅格/网格的确切性质。


0
投票

我认为阈值为 123.45...然后:

WITH 
threshold AS 
(SELECT 123.45 AS threshold_value, MIN(value) AS MI, MAX(value) AS MA 
 FROM foo),
slices AS
(SELECT threshold_value, GENERATE_SERIES AS boundary  
 FROM   threshold
        LATERAL GENERATE_SERIES(MI - threshold_value / 2.0, MA + threshold_value / 2.0, threshold_value) AS boundaries),
places AS 
(SELECT Id, val, boundary, threshold_value
 FROM   foo
        JOIN slices ON val >= boundary AND val < boundary + threshold_value)
SELECT  COUNT(val) AS COUNT_VAL, boundary AS BOUND_LOW, boundary + threshold_value AS BOUND_HIGH
FROM    places
GROUP   BY boundary, boundary + threshold_value
ORDER   BY BOUND_LOW;

未测试...

© www.soinside.com 2019 - 2024. All rights reserved.