获取具有JSONB上的值的行,如果该值不存在,则获取行

时间:2018-12-28 11:42:45

标签: sql postgresql jsonb

我有一个名为credentials的表,该表具有一个称为jsonb的{​​{1}}列和一个名为details的列。 user_id列有一个名为details的数组,该数组可以为空,也可以包含以下对象:systems

我有以下查询,伪装为每个用户获取给定system_id的所有system_values:

{ system_id: TXT, system_value: TXT }

这很好。但是,如果用户之一:

  1. 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' 数组内没有任何对象,或者
  2. 没有具有给定credentials的对象

它不会为他们返回一行。我想返回一行说system_idsystem_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并不是问题。

1 个答案:

答案 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)    

Try it in rextester.