在 postgres 中使用 json 数组在同一个 table 上进行多个可选连接
Making multiple optional joins on same table using json array in postgres
我有两个表 users 和 rooms。我正在尝试加入这两个表并获取与房间相关的用户名列表。只有当两列都有值时,我才会得到结果。如果任何一列为空,则它不会给出非空列的值。请在下面找到详细信息。
用户架构:
id name
---------
1 X
3 Y
4 Z
房间架构:
id active_users inactive_users
-----------------------------------
101 [1] [3]
102 [3] null
103 null [4]
尝试查询:
SELECT
r.id, json_agg(u.name) as active_users, json_agg(u1.name) as inactive_users
FROM rooms r,
json_array_elements(active_users) as elems
LEFT OUTER JOIN users u
ON u.id = elems::TEXT::INT,
json_array_elements(inactive_users) as elems1
LEFT OUTER JOIN users u1 ON
u1.id = elems1::TEXT::INT
GROUP BY r.id
查询输出:
id active_users inactive_users
----------------------------------
101 ["X"] ["Y"]
预期输出:
id active_users inactive_users
----------------------------------
101 ["X"] ["Y"]
102 ["Y"] NULL
103 NULL ["Z"]
这里的主要问题是您正在使用 json_array_elements(active_users)
函数进行内部联接,当 active_users
为 null 时该函数会生成 null。因此,该联接排除了您要包括的那些行。如果您也将这些连接变成外部连接,它将起作用:
SELECT
r.id,
json_agg(u.name) FILTER (WHERE u.name IS NOT NULL) as active_users,
json_agg(u1.name) FILTER (WHERE u1.name IS NOT NULL) as inactive_users
FROM rooms r
LEFT JOIN json_array_elements(active_users) as elems
ON TRUE
LEFT JOIN json_array_elements(inactive_users) as elems1
ON TRUE
LEFT JOIN users u
ON u.id = elems::TEXT::INT
LEFT JOIN users u1 ON
u1.id = elems1::TEXT::INT
GROUP BY r.id;
您会注意到我还在 select 中添加了 FILTER
s,这样空用户名就被排除在聚合之外。
我有两个表 users 和 rooms。我正在尝试加入这两个表并获取与房间相关的用户名列表。只有当两列都有值时,我才会得到结果。如果任何一列为空,则它不会给出非空列的值。请在下面找到详细信息。
用户架构:
id name
---------
1 X
3 Y
4 Z
房间架构:
id active_users inactive_users
-----------------------------------
101 [1] [3]
102 [3] null
103 null [4]
尝试查询:
SELECT
r.id, json_agg(u.name) as active_users, json_agg(u1.name) as inactive_users
FROM rooms r,
json_array_elements(active_users) as elems
LEFT OUTER JOIN users u
ON u.id = elems::TEXT::INT,
json_array_elements(inactive_users) as elems1
LEFT OUTER JOIN users u1 ON
u1.id = elems1::TEXT::INT
GROUP BY r.id
查询输出:
id active_users inactive_users
----------------------------------
101 ["X"] ["Y"]
预期输出:
id active_users inactive_users
----------------------------------
101 ["X"] ["Y"]
102 ["Y"] NULL
103 NULL ["Z"]
这里的主要问题是您正在使用 json_array_elements(active_users)
函数进行内部联接,当 active_users
为 null 时该函数会生成 null。因此,该联接排除了您要包括的那些行。如果您也将这些连接变成外部连接,它将起作用:
SELECT
r.id,
json_agg(u.name) FILTER (WHERE u.name IS NOT NULL) as active_users,
json_agg(u1.name) FILTER (WHERE u1.name IS NOT NULL) as inactive_users
FROM rooms r
LEFT JOIN json_array_elements(active_users) as elems
ON TRUE
LEFT JOIN json_array_elements(inactive_users) as elems1
ON TRUE
LEFT JOIN users u
ON u.id = elems::TEXT::INT
LEFT JOIN users u1 ON
u1.id = elems1::TEXT::INT
GROUP BY r.id;
您会注意到我还在 select 中添加了 FILTER
s,这样空用户名就被排除在聚合之外。