Получить строки со значениями в JSONB, а также, если строки, если значение не существует - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть таблица с именем credentials, в которой есть столбец jsonb с именем details и столбец с именем user_id.Столбец details имеет массив с именем systems, который может быть либо пустым, либо содержать объекты, которые выглядят следующим образом: { system_id: TXT, system_value: TXT }

У меня есть следующий запрос, который претендует на получение всех значений system_value дляданный system_id для каждого из пользователей:

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'

Это прекрасно работает.Однако, если пользователь либо:

  1. Не имеет никаких объектов внутри массива credentials ИЛИ
  2. Не имеет объекта с данным 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

Но с моим текущим запросом я просто получаю:

user_id, system_value
1, "success"

Как мне изменить запрос, чтобы учесть те учетные данные, которые не имеют ни одного значения на'systems' или ни одно из значений для данного 'system_id'?

Обратите внимание, что даже если я это сделаю:

SELECT credentials.user_id, systems->>'system_value' AS system_value
FROM  credentials, jsonb_array_elements(credentials.details->'systems') systems

Он не вернет пользователей, у которых нет credentails.details с любыми элементами вообще.Поэтому я не думаю, что проблема where.

1 Ответ

0 голосов
/ 28 декабря 2018

Используйте 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)    

Попробуйте в rextester.

...