Postgresql根据另一个字段的变化更改值

时间:2014-11-17 17:51:53

标签: sql postgresql window-functions

我有一个像这样的Postgres表:

 id | value
----+-------
  1 |   100
  2 |   100   
  3 |   100   
  4 |   100       
  5 |   200
  6 |   200    
  7 |   200       
  8 |   100
  9 |   100
 10 |   300

我有一张这样的表

 id | value   |new_id
----+---------+-----
  1 |   100   |  1
  2 |   100   |  1
  3 |   100   |  1
  4 |   100   |  1 
  5 |   200   |  2
  6 |   200   |  2
  7 |   200   |  2
  8 |   100   |  3
  9 |   100   |  3
 10 |   300   |  4

我有一个新字段,其中new_id会在值更改时更改,并且在值再次更改之前保持不变。 我的问题类似this但我无法找到解决方案。

1 个答案:

答案 0 :(得分:3)

您可以使用row_number()的差异来识别值相同的序列。获得差异后,您有一个组标识符,可以计算每个组的最小ID。然后,dense_rank()将根据此顺序重新编号值。

看起来像这样:

select t.id, t.value, dense_rank() over (order by minid) as new_id
from (select t.*, min(id) over (partition by value, grp) as minid
      from (select t.*,
                   (row_number() over (order by id) - row_number() over (partition by value order by id)
                   ) as grp
            from table t
           ) t
     ) t

您可以看到示例数据会发生什么:

 id | value | grp | minid | new_id |
----+-------+-----+-------+--------+
  1 |   100 |  0  |   1   |    1   |
  2 |   100 |  0  |   1   |    1   | 
  3 |   100 |  0  |   1   |    1   |
  4 |   100 |  0  |   1   |    1   |
  5 |   200 |  4  |   5   |    2   |
  6 |   200 |  4  |   5   |    2   |
  7 |   200 |  4  |   5   |    2   |
  8 |   100 |  3  |   8   |    3   |
  9 |   100 |  3  |   8   |    3   |
 10 |   300 |  9  |  10   |    4   |