postgres 按行聚合子集

postgres aggregate subset from group by rows

我正在尝试评估半年不活动后奖金消耗时的用户忠诚度奖金余额。我希望我的总和包含用户 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

这是您要找的吗?

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

试试这个:

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

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