如何将增量计数器添加到分组行,每次变量更改时重置计数器

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

我有一个PostgreSQL表包含:person_identifier,period_identifier,status

 person | period | status 
 -------+--------+--------
   Bob  |   Jan  | new    
   Bob  |   Feb  | retained    
   Bob  |   Mar  | retained 
   Bob  |   Apr  | dormant 
   Bob  |   May  | dormant 
   Bob  |   Jun  | resurected 
   Bob  |   Jul  | retained
   Bob  |   Agu  | dormant
   Jim  |   Jan  | new
   Jim  |   Feb  | dormant
   Jim  |   Mar  | dormant
   Jim  |   Apr  | dormant 
   Jim  |   May  | dormant
   Jim  |   Jun  | resurected
   Jim  |   Jul  | dormant
   Jim  |   Agu  | resurected

我需要的是包括counterperson, status分组,其限制是只要状态改变,计数器就需要重新启动到1。

我尝试了以下查询,但只要状态发生变化,这就不会将计数器降低到1:

reset

这是我的查询与实际需要的区别; SELECT *, ROW_NUMBER() OVER (PARTITION BY person, status ORDER BY period) AS wrong_counter FROM my_table

* stands for wrong value

谁能帮我这个?

sql postgresql
1个回答
0
投票

我做了一些规范化:

 person | period |    status   | wrong_counter | needed_counter
 -------+--------+-------------+ --------------+---------------
   Bob  |   Jan  | new         |      1        |       1       
   Bob  |   Feb  | retained    |      1        |       1       
   Bob  |   Mar  | retained    |      2        |       2       
   Bob  |   Apr  | dormant     |      1        |       1       
   Bob  |   May  | dormant     |      2        |       2       
   Bob  |   Jun  | resurected  |      1        |       1       
   Bob  |   Jul  | retained    |      3*       |       1       
   Bob  |   Agu  | dormant     |      3*       |       1       
   Jim  |   Jan  | new         |      1        |       1       
   Jim  |   Feb  | dormant     |      1        |       1       
   Jim  |   Mar  | dormant     |      2        |       2       
   Jim  |   Apr  | dormant     |      3        |       3       
   Jim  |   May  | dormant     |      4        |       4       
   Jim  |   Jun  | resurected  |      1        |       1       
   Jim  |   Jul  | dormant     |      5*       |       1       
   Jim  |   Agu  | resurected  |      2*       |       1       

并用作basetable:public.tbl_test

然后我做一些计算:首先获取实际行之前的行中的状态,是否为status_change。创建一个help_partition,然后在help_partition上获取row_number。

person -> person_fk,
period -> period_int, Jan = 1 ...
status -> status_fk

并导致:(最后一行是你需要的计数器)

with temp_base_data as 
(
select
 *,
lag(status_fk,1,-1) over(ORDER BY person_fk, period_int) as status_before,
case
when lag(status_fk,1,-1)  over(ORDER BY person_fk, period_int) = status_fk and  lag(person_fk ,1,-1) over(ORDER BY person_fk, period_int) = person_fk 
    then 0
else 1
end as status_change
from public.tbl_test
order by person_fk, period_int
),
temp_partition  AS
(
select 
*,
sum(status_change) over ( order by  person_fk, period_int  RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as help_partition
from temp_base_data
order by person_fk, period_int
)

select
 * ,
row_number() over (PARTITION by help_partition order by person_fk, period_int) as counter
from temp_partition 
order by id
© www.soinside.com 2019 - 2024. All rights reserved.