从子查询更新PostgreSQL

时间:2016-11-03 10:39:32

标签: postgresql

我有一个以下的PostgreSQL表:

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)
);

根据此表中的数据,我需要更新:

    每个行的
  1. created_by字段user_id来自此表 其中created_by_old = user_old_id请注意created_by_old可以为NULL,因此在这种情况下必须避免。

  2. last_updated_by此表格中包含user_id的字段 last_updated_by_old = user_old_id行请注意last_updated_by_old可以为NULL,因此在这种情况下必须避免。

  3. 这是一个示例数据:

    实际

    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            |                 | 
    

    预期:

    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            |                 | 
    

    我认为它可以用子查询实现,但现在不能自己弄清楚如何实现这个查询。请帮忙。

2 个答案:

答案 0 :(得分:1)

效率不高,但如果这不是问题,你可以这样做:

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)

答案 1 :(得分:1)

如果您想要更高效的更新语句,可以使用派生表来获取您想要的信息作为更新语句的来源:

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;

通常不应在from子句中重复更新的目标表,但这种情况是一个罕见的例子,无法避免。

但如果user_old_id也是唯一的,那么才会正常工作,而不仅仅是user_id

在线示例:http://rextester.com/HKM21985