如何根据条件创建一个递增1的标志

时间:2017-05-16 21:53:24

标签: postgresql aggregate-functions window-functions

如何通过查看连续变量的值来创建标志?

例如,在下面的表格(图片)中,

对于第1行,flag取值1;

对于第2行,它会检查:

  If variable1 =lag(variable2) 
 and variable2=lag(variable1) then flag = lag(flag) else flag increments by 1. 

在这种情况下,条件不匹配,因此标志取值为2.

第3行:    由于它匹配上述条件标志与2

相同

对于第4行:即使它符合上述条件,标志也会更改为3,因为之前的2行(第2行和第3行)已匹配

等等..

最终标志如下:

enter image description here

1 个答案:

答案 0 :(得分:1)

请记住,您最好对输入数据进行排序,以实现基于2行聚合的“移动标记”。为了这个答案,我添加了一个row_number()函数来生成给出样本数据的顺序。

测试数据

create table flagtest( var1 text, var2 text);
insert into flagtest(var1,var2) values 
  ('T','Z'),('B','A'),('A','B'),('B','A'),('A','B'),('A','B'),
  ('A','B'),('B','A'),('C','D'),('E','F'),('F','E'),('M','N');

<强>代码

-- fourth part
select var1, var2, sum(change_flag_2_based) over (order by ordcol) as flag
from( -- third part
  select *, 
    case when 
      lag(change_flag) over (order by ordcol) = 0
      and lag(change_flag, 2) over (order by ordcol) = 1
      then 1 else change_flag 
    end as change_flag_2_based
  from ( -- second part
    select
      var1, var2, ordcol,
      case when 
        var1 = lag(var2) over (order by ordcol) and 
        var2 = lag(var1) over (order by ordcol) 
        then 0 else 1 
      end as change_flag 
    from ( -- first part
      select var1, var2, row_number() over () as ordcol
      from flagtest
      ) ordered_data
    ) prep_aggr_all
  ) prep_aggr_two_rows_based;

它是如何运作的?

  • 第一部分是关于提供一个列以便稍后在窗口函数中对输入数据进行排序。这将是您目前在表中的任何其他列。在示例中,它引入了row_number()窗口函数来生成这样的数字顺序。

  • 第二部分是我们标记行的位置,假设两个变量之间的交叉平等策略比较当前行与前一行,指示符1和0是否该标志应该在此特定行中更改。这不是一个基于2的对聚合(尚未)。

  • 第三部分介绍将当前行更改标志指示器与前两行的指示器进行比较,如果后面的1行没有改变标志,后面的2行确实改变它,则意味着我们应该将当前行标记为标志 - 改变(基于2行的标志)。

  • 第四部分仅用于移动总和,通过对这些组进行求和来制作最终标志。

<强>输出

 var1 | var2 | flag
------+------+------
 T    | Z    |    1
 B    | A    |    2
 A    | B    |    2
 B    | A    |    3
 A    | B    |    3
 A    | B    |    4
 A    | B    |    5
 B    | A    |    5
 C    | D    |    6
 E    | F    |    7
 F    | E    |    7
 M    | N    |    8