Reputation: 878
I have a Postgres table like this:
id | value
----+-------
1 | 100
2 | 100
3 | 100
4 | 100
5 | 200
6 | 200
7 | 200
8 | 100
9 | 100
10 | 300
I'd have a table like this
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
I'd have a new field with a new_id that change when value change and remain the same until value changes again. My question is similar this but I cannot found a solution.
Upvotes: 0
Views: 619
Reputation: 1269863
You can identify sequences where the value is the same by using a difference of row_number()
. After getting the difference, you have a group identifier and can calculate the minimum id for each group. Then, dense_rank()
will renumber the values based on this ordering.
It looks like this:
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
You can see what happens to your sample data:
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 |
Upvotes: 3