0

for example i have column that look like this:

name | id | value 
A      1     aa 
A      2     ab 
B      3     bc 
C      4     ca 
C      5     cb

Is there any way to change it to this ?

name | id | value 
A      1     aa 
A      1     ab 
B      3     bc 
C      4     ca 
C      4     cb
2
  • 1
    Do you want to permanently change those values (i.e. run an update statement) or do you just want to display the values like that (i.e. in a select statement) Commented Sep 28, 2015 at 7:22
  • Permanently @a_horse_with_no_name Commented Sep 28, 2015 at 7:26

1 Answer 1

2

You can do this with a window function that numbers the rows, and use that select statement to supply the values for the update:

update the_table
  set id = t.rn
from (
  select name, 
         id, 
         dense_rank() over (order by name)  as rn
  from the_table
) t
where (t.name, t.id) = (the_table.name, the_table.id);

SQLFiddle example: http://sqlfiddle.com/#!15/0e987/1

This assumes that the existing combination (id, name) is unique. If that is not the case, you would need to use the ctid column to match the rows between the inner select and the table itself:

update the_table
  set id = t.rn
from (
  select name, 
         id, 
         ctid,
         dense_rank() over (order by name)  as rn
  from the_table
) t
where t.ctid = the_table.ctid;
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you very much, but i have one more question. If i don't have the name column, but only (id, values) and i want to do the same, i need to use ctid, right ?
@BilboBagosz: yes, if you don't have a unique identifier for a row, then you have to use ctid. This is one of the rare situations where it can safely be used as a key.
one more thing. If i have id with larger numbers for example: (1275868, 1275958, 1275910) how i can resolve the same problem? Is there any function like to dense_rank which can handle with that ?
@BilboBagosz: what exactly do you mean with "can handle that"? What is the problem you have?
dense_rank is good when i want to order id from 1. But if i have id which are not numbered from 1, but have different values. For example: A | 152 | ca A | 173 | cb B | 163 | ba C | 285 | bb C | 273 | be And i want to look like this: A | 152 | ca A | 152 | cb B | 163 | ba C | 285 | bb C | 285 | be
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.