在 postgres 中使用 json 数组在同一个 table 上进行多个可选连接

Making multiple optional joins on same table using json array in postgres

我有两个表 usersrooms。我正在尝试加入这两个表并获取与房间相关的用户名列表。只有当两列都有值时,我才会得到结果。如果任何一列为空,则它不会给出非空列的值。请在下面找到详细信息。

用户架构:

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 中添加了 FILTERs,这样空用户名就被排除在聚合之外。