问题描述
我有两张桌子用户和房间。我正在尝试加入两个表并获取与房间相关的用户名列表。只有当两列都有值时,我才会得到结果。如果任何一列为空,则不会给出非空列的值。请在下面找到详细信息。
用户架构:
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;
您会注意到我还在选择中添加了 FILTER
,因此从聚合中排除了空用户名。