如何使用两个表中的数据建立关系?
How to build relationships using data from two tables?
我正在 Postgres 中构建迁移,我需要为每个组织添加一个新用户。
假设我有树表:
- 用户
- 组织
- user_org
数据库中已经存在组织列表。
现在我正在根据其他用户和修改后的数据创建新用户,如下所示:
insert into users
select
...
from users where ...
returning id
我现在需要的是将每个用户关联到一个组织(假设创建的用户数和组织数匹配)。
cross join
不会起作用,因为它将所有用户关联到所有组织。
鉴于新创建的用户具有不同的密钥,我从中复制的用户列表已经与组织相关联,是否有一种简单的方法可以基于该列表构建我的查询?
如果我理解正确,这里有一个选项使用 inner join
,然后根据 table 到 join
在:[=15= 上建立 row_number
]
insert into user_org
select u.id, o.id
from (select id, row_number() over (order by id) rn
from usr) u join
(select id, row_number() over (order by id) rn
from org) o on u.rn = o.rn
The list of users that I am copying from already associated with orgs, is there an easy way to build my query based on that, given that newly created users have different keys?
如果有任何列子集可以在没有 PK 的情况下识别唯一用户,则有一个带有数据修改 CTE 的安全解决方案。您甚至可以一次插入多个用户副本:
WITH template_user AS (
SELECT u.*, uo.org_id -- include the connected org_id
FROM users u
JOIN user_org uo ON uo.user_id = u.id -- guessing column names
WHERE ... -- make sure exactly *one* desired org is joined
)
, ins_user AS (
INSERT INTO users u (...)
SELECT ...
FROM template_user t
WHERE ...
RETURNING *
)
INSERT INTO user_org (user_id, org_id)
SELECT iu.id, tu.org_id
FROM ins_user iu
JOIN template_user tu USING (<list of columns that secures distinct join>)
RETURNING *; -- optional
在不太可能的情况下,您不应该有一组可靠的列来连接到模板用户:添加行号,如 ,但在实际有效的查询中:
WITH template_usr AS (
SELECT u.*, uo.org_id -- include the connected org_id
row_number() OVER () AS rn -- arbitrary number
FROM usr u
JOIN usr_org uo ON uo.usr_id = u.id -- guessing column names
WHERE ... -- make sure exactly *one* desired org is joined
)
, ins_usr AS (
INSERT INTO usr u (...) -- add target columns
SELECT ...
FROM template_usr
ORDER BY rn -- insert in same order!
RETURNING id
)
INSERT INTO usr_org (usr_id, org_id)
SELECT iu.id, tu.org_id
FROM (
SELECT id, row_number() OVER (ORDER BY id) AS rn
FROM ins_usr
) iu
JOIN template_usr tu USING (rn)
RETURNING *; -- optional
相关:
Insert data in 3 tables at a time using Postgres
Create a new table (multiple columns) by selecting random values from an existing table
我正在 Postgres 中构建迁移,我需要为每个组织添加一个新用户。
假设我有树表:
- 用户
- 组织
- user_org
数据库中已经存在组织列表。
现在我正在根据其他用户和修改后的数据创建新用户,如下所示:
insert into users
select
...
from users where ...
returning id
我现在需要的是将每个用户关联到一个组织(假设创建的用户数和组织数匹配)。
cross join
不会起作用,因为它将所有用户关联到所有组织。
鉴于新创建的用户具有不同的密钥,我从中复制的用户列表已经与组织相关联,是否有一种简单的方法可以基于该列表构建我的查询?
如果我理解正确,这里有一个选项使用 inner join
,然后根据 table 到 join
在:[=15= 上建立 row_number
]
insert into user_org
select u.id, o.id
from (select id, row_number() over (order by id) rn
from usr) u join
(select id, row_number() over (order by id) rn
from org) o on u.rn = o.rn
The list of users that I am copying from already associated with orgs, is there an easy way to build my query based on that, given that newly created users have different keys?
如果有任何列子集可以在没有 PK 的情况下识别唯一用户,则有一个带有数据修改 CTE 的安全解决方案。您甚至可以一次插入多个用户副本:
WITH template_user AS (
SELECT u.*, uo.org_id -- include the connected org_id
FROM users u
JOIN user_org uo ON uo.user_id = u.id -- guessing column names
WHERE ... -- make sure exactly *one* desired org is joined
)
, ins_user AS (
INSERT INTO users u (...)
SELECT ...
FROM template_user t
WHERE ...
RETURNING *
)
INSERT INTO user_org (user_id, org_id)
SELECT iu.id, tu.org_id
FROM ins_user iu
JOIN template_user tu USING (<list of columns that secures distinct join>)
RETURNING *; -- optional
在不太可能的情况下,您不应该有一组可靠的列来连接到模板用户:添加行号,如
WITH template_usr AS (
SELECT u.*, uo.org_id -- include the connected org_id
row_number() OVER () AS rn -- arbitrary number
FROM usr u
JOIN usr_org uo ON uo.usr_id = u.id -- guessing column names
WHERE ... -- make sure exactly *one* desired org is joined
)
, ins_usr AS (
INSERT INTO usr u (...) -- add target columns
SELECT ...
FROM template_usr
ORDER BY rn -- insert in same order!
RETURNING id
)
INSERT INTO usr_org (usr_id, org_id)
SELECT iu.id, tu.org_id
FROM (
SELECT id, row_number() OVER (ORDER BY id) AS rn
FROM ins_usr
) iu
JOIN template_usr tu USING (rn)
RETURNING *; -- optional
相关:
Insert data in 3 tables at a time using Postgres
Create a new table (multiple columns) by selecting random values from an existing table