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

时间:2018-11-15 00:15:35

标签: sql postgresql

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

using System.Windows.Forms;
public static class TreeViewExtensiona
{
    public static TreeNode FindByPath(this TreeNodeCollection nodes, string path)
    {
        TreeNode found = null;
        foreach (TreeNode n in nodes)
        {
            if (n.FullPath == path)
                found = n;
            else
                found = FindByPath(n.Nodes, path);
            if (found != null)
                return found;
        }
        return null;
    }
}

我需要包括一个 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 分组的counter,并限制状态变化时计数器必须重新启动为1。

我尝试了以下查询,但是每当状态更改时,计数器都不会person, status降至1:

reset

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

* stands for wrong value

有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

我做了一些归一化:

DateTime

并用作基表: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