3

I have a following PostgreSQL table:

CREATE TABLE users (
    user_id INTEGER DEFAULT nextval('users_user_id_seq') NOT NULL,
    user_old_id CHARACTER VARYING(36),
    created_by INTEGER,
    created_by_old character varying(36),
    last_updated_by INTEGER,
    last_updated_by_old character varying(36),
    CONSTRAINT users_pkey PRIMARY KEY (user_id)
);

Based on data in this table I need to update:

  1. created_by field with user_id from this table for every row where created_by_old = user_old_id Please note that created_by_old can be NULL and therefore must be avoided in this case.

  2. last_updated_by field with user_id from this table for every row where last_updated_by_old = user_old_id Please note that last_updated_by_old can be NULL and therefore must be avoided in this case.

This is a sample data:

Actual:

user_id | user_old_id | created_by | created_by_old | last_updated_by | last_updated_by_old 
--------------------------------------------------------------------------------------------
1       | aaa         |            | ccc            |                 | bbb
--------------------------------------------------------------------------------------------
2       | bbb         |            | ddd            |                 | aaa
--------------------------------------------------------------------------------------------
3       | ccc         |            |                |                 | ddd
--------------------------------------------------------------------------------------------
4       | ddd         |            | aaa            |                 | 

Expected:

user_id | user_old_id | created_by | created_by_old | last_updated_by | last_updated_by_old 
--------------------------------------------------------------------------------------------
1       | aaa         |  3         | ccc            |   2             | bbb
--------------------------------------------------------------------------------------------
2       | bbb         |  4         | ddd            |   1             | aaa
--------------------------------------------------------------------------------------------
3       | ccc         |            |                |   4             | ddd
--------------------------------------------------------------------------------------------
4       | ddd         |  1         | aaa            |                 | 

I think it can be implemented with a subquery but can't figure out by myself right now how to implement this query. Please help.

3
  • Please provide data sample and expected output. Commented Nov 3, 2016 at 10:42
  • What did you try until now ? Commented Nov 3, 2016 at 10:44
  • @sagi I have updated my question with a sample data and expected result Commented Nov 3, 2016 at 10:56

2 Answers 2

8

If you want a more efficient update statement you can use a derived table that gets the information you want as the source of your update statement:

update users u1
  set created_by = t.new_created_by, 
      last_updated_by = t.new_updated_by
from ( 
  select u2.user_id, u2.user_old_id,
         cr.user_id as new_created_by, 
         lu.user_id as new_updated_by
  from users u2
    left join users cr on cr.user_old_id = u2.created_by_old
    left join users lu on lu.user_old_id = u2.last_updated_by_old
) t
where t.user_id = u1.user_id;

Usually the target table of the update should never be repeated in the from clause, but this case is a rare example where it can't be avoided.

But this will only work properly if user_old_id is also unique, not only user_id.

Online example: http://rextester.com/HKM21985

Sign up to request clarification or add additional context in comments.

Comments

4

Not too efficient ,but if that's not an issue you can do this :

UPDATE users u
SET u.created_by = (SELECT t.user_id FROM users t
                    WHERE u.created_by_old = t.user_old_id),
    u.last_updated_by = (SELECT s.user_id FROM users s
                         WHERE u.last_updated_by = s.user_old_id)

4 Comments

Thanks. Please note that created_by_old or last_updated_by_old in some rows can be empty and therefore update of appropriate field must be avoided in this case. How to update this query in order to support this case ?
Why? If it's NULL then the result will be NULL as well . @alexanoid
Thanks. Also I tried this query UPDATE users u SET u.created_by = (SELECT t.user_id FROM users t WHERE u.created_by_old = t.user_old_id), u.last_updated_by = (SELECT s.user_id FROM users s WHERE u.last_updated_by_old = s.user_old_id) but it fails with a following error: ERROR: column "u" of relation "users" does not exist LINE 1: UPDATE users u SET u.created_by = (SELECT t.user_id FROM use...
I have updated u.created_by to simple created_by and now everything works fine! Thank you !

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.