postgres 按行聚合子集

Posted

技术标签:

【中文标题】postgres 按行聚合子集【英文标题】:postgres aggregate subset from group by rows 【发布时间】:2021-08-08 18:26:30 【问题描述】:

我正在尝试评估半年不活动后奖金消耗殆尽时的用户忠诚度奖金余额。我希望我的总和由用户 1 的 ord 的 4、5 和 6 组成。

create table transactions (
    user int,
    ord int, -- transaction date replacement
    amount int, 
    lag interval -- after previous transaction
);
insert into transactions values
    (1, 1, 10, '1h'::interval),
    (1, 2, 10, '.5y'::interval),
    (1, 3, 10, '1h'::interval),
    (1, 4, 10, '.5y'::interval),
    (1, 5, 10, '.1h'::interval),
    (1, 6, 10, '.1h'::interval),
    (2, 1, 10, '1h'::interval),
    (2, 2, 10, '.5y'::interval),
    (2, 3, 10, '.1h'::interval),
    (2, 4, 10, '.1h'::interval),
    (3, 1, 10, '1h'::interval),
;

select user, sum(
    amount -- but starting from last '.5y'::interval if any otherwise everything counts
) from transactions group by user 

 user | sum(amount)
--------------------
 1    | 30 -- (4+5+6), not 50, not 60
 2    | 30 -- (2+3+4), not 40
 3    | 10

【问题讨论】:

既然你解释了你期望的结果,我的回答应该会给你一个很好的结果 好吧,我根据您的建议添加的最后一条数据无法按预期工作。努力改进。 【参考方案1】:

这是你要找的吗?

with last_5y as(
    select "user", max(ord) as ord
    from transactions
    where lag = '.5y'::interval group by "user"
) select t.user, sum(amount)
    from transactions t, last_5y t2
    where t.user = t2.user and t.ord >= t2.ord
    group by t.user

【讨论】:

如果您在查询的 cmets 中写下您的问题,如何期望得到好的答案? 您必须应用间隔的日期在哪里? 它以ord字段替换表示,lag是预先计算的当前和以前事务之间的间隔 如果这是您要找的,我已经修改了我的答案。 Ord 是一个整数。您的日期是否保存为整数? 没有。感谢您的努力,但我的问题更复杂。也许我必须重新考虑问题描述。无论如何,谢谢!【参考方案2】:

试试这个:

with cte as(
select *, 
case when (lead(lag) over (partition by user_ order by ord)) >= interval '.5 year'
then 1 else 0  end  "flag" from test
),
cte1 as (
select *,
case when flag=(lag(flag,1) over (partition by user_ order by ord)) then 0 else 1 end "flag1"  from cte
)
select distinct on (user_) user_, sum(amount) over (partition by user_,grp order by ord) from (
select *, sum(flag1) over (partition by user_ order by ord) "grp" from cte1) t1
order by user_ , ord desc

DEMO

虽然很复杂很慢但是可以解决你的问题

【讨论】:

哇!看起来很赚钱!无论如何,我正在尝试使 create view as (... 摆脱这种状态。你认为它作为视图会更快吗? 当然它会更好,而且你可以将它用作桌子 另一种思路是把所有with语句变成相互查询的中间视图。

以上是关于postgres 按行聚合子集的主要内容,如果未能解决你的问题,请参考以下文章

Postgres 聚合

Postgres 聚合 Hstore

Postgres Jsonb 聚合

Postgres - 将两列聚合为一项

Django/Postgres:在 RangeField 上聚合

postgres 按聚合函数分组