在postgres表中所有唯一阈值上“区别开”

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

我有一个叫做sample_a的Postgres 11表,看起来像这样:

 time | cat | val
------+-----+-----
    1 |   1 |   5
    1 |   2 |   4
    2 |   1 |   6
    3 |   1 |   9
    4 |   3 |   2

我想创建一个查询,该查询针对每个唯一的时间步长,获取该时间步长处或之前的每个类别的最新值,并通过取这些值的总和除以这些值的计数来汇总这些值。

我相信我有查询要在给定的时间范围内执行此操作。例如,对于时间3,我可以运行以下查询:

select sum(val)::numeric / count(val) as result from (
    select distinct on (cat) * from sample_a where time <= 3  order by cat, time desc
) x;

并获得6.5。 (这是因为在时间3上,类别1的最新值为9,类别2的最新值为4。值的计数为2,它们的总和为[ C0],13 / 132。)

但是,理想情况下,我希望运行一个查询,该查询将为我提供表中每个唯一时间的所有结果。该新查询的输出如下所示:

6.5

理想情况下,此新查询将避免添加另一个子选择子句;一个高效的查询将是首选。我可以通过在每个时间步长在应用程序中运行先前的查询来获得这些先前的结果,但是对于大的 time | result ------+---------- 1 | 4.5 2 | 5 3 | 6.5 4 | 5 来说,这似乎并不高效。

此新查询的外观如何?

sql postgresql performance distinct distinct-on
2个回答
1
投票

看看这种性能是否可以接受。语法可能需要细微调整:

sample_a

0
投票

我认为您只需要累积函数:

select t.time, avg(mr.val) as result
from (select distinct time from sample_a) t,
    lateral (
        select distinct on (cat) val
        from sample_a a
        where a.time <= t.time
        order by a.cat, a.time desc
    ) mr
group by t.time

请注意,如果select time, sum(sum(val)) over (order by time) / sum(sum(num_val)) over (order by time) as result from (select time, sum(val) as sum_val, count(*) as num_val from sample_a a group by time ) a; 是整数,则可能需要转换为数字以获取小数值。

这也可以不用子查询来表达:

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