我有一个名为credentials
的表,该表具有一个称为jsonb
的{{1}}列和一个名为details
的列。 user_id
列有一个名为details
的数组,该数组可以为空,也可以包含以下对象:systems
我有以下查询,伪装为每个用户获取给定system_id的所有system_values:
{ system_id: TXT, system_value: TXT }
这很好。但是,如果用户之一:
SELECT credentials.user_id, systems->>'system_value' AS system_value
FROM credentials, jsonb_array_elements(credentials.details->'systems') systems
WHERE systems->>'system_id' = 'a-given-id'
数组内没有任何对象,或者credentials
的对象它不会为他们返回一行。我想返回一行说system_id
是system_value
。
例如,对于给定的数据:
NULL
我希望查询后得到:
user_id, credentials
1, { "systems": [{ "system_id": "x", "system_value": "success" }] }
2, { "systems": [{ "system_id": "y", "system_value": "failure" }] }
3, { "systems": [] }
但是通过当前查询,我得到了:
user_id, system_value
1, "success"
2, NULL
3, NULL
我应该如何修改查询以考虑那些没有“ systems”值或没有给定“ system_id”值的凭据?
请注意,即使我这样做:
user_id, system_value
1, "success"
它不会返回完全没有任何元素的SELECT credentials.user_id, systems->>'system_value' AS system_value
FROM credentials, jsonb_array_elements(credentials.details->'systems') systems
用户。因此,我认为credentails.details
并不是问题。
答案 0 :(得分:1)
使用LEFT JOIN ... ON true
获取所有行:
SELECT credentials.user_id, systems->>'system_value' AS system_value
FROM credentials
LEFT JOIN jsonb_array_elements(credentials.details->'systems') systems ON true
user_id | system_value
---------+--------------
1 | success
2 | failure
3 |
(3 rows)
如果要获取具有给定system_id
值的所有行,则应在SELECT
中使用条件表达式,因为WHERE
中的条件只是过滤行:
SELECT
c.user_id,
CASE systems->>'system_id'
WHEN 'x' THEN systems->>'system_value'
ELSE null
END AS system_value
FROM credentials c
LEFT JOIN jsonb_array_elements(c.details->'systems') systems ON true
user_id | system_value
---------+--------------
1 | success
2 |
3 |
(3 rows)