PostgreSQL преобразовать значение из столбца jsonb в другой столбец - PullRequest
0 голосов
/ 10 апреля 2020

У меня есть PostgreSQL база данных v10 со следующими данными:

CREATE TABLE test (
  id INT,
  custom_fields jsonb not null default '{}'::jsonb,
  guest_profile_id character varying(100)
);
INSERT INTO test (id, custom_fields) VALUES (1, '[{"protelSurname": "Smith", "servicio_tags": ["protel-info"], "protelUniqueID": "[{\"ID\":\"Test1-ID\",\"Type\":\"21\",\"ID_Context\":\"GHA\"}{\"ID\":\"4842148\",\"Type\":\"1\",\"ID_Context\":\"protelIO\"}]",    "protelGivenName": "Seth"}, {"value": "Test", "display_name": "Traces", "servicio_tags": ["trace"]}, {...}]');
INSERT INTO test (id, custom_fields) VALUES (2, '[{"protelSurname": "Smith", "servicio_tags": ["protel-info"], "protelUniqueID": "[{\"ID\":\"Test2-ID\",\"Type\":\"21\",\"ID_Context\":\"GHA\"},{\"ID\":\"4842148\",\"Type\":\"1\",\"ID_Context\":\"protelIO\"}]", "protelGivenName": "Seth"}, {"value": "Test2", "display_name": "Traces", "servicio_tags": ["trace"]}, {...}]');
INSERT INTO test (id, custom_fields) VALUES (3, '[{"value": "Test3-ID", "display_name": "Test", "servicio_tags": ["person-name"]}, {...}]');
INSERT INTO test (id, custom_fields) VALUES (4, '[{"value": "Test4-ID", "display_name": "Test", "servicio_tags": ["profile-id"]}, {...}]');

В реальной таблице гораздо больше записей.

Цель: Я хочу перенести значения TestX-ID в столбец guest_profile_id в той же строке. И только эти значения, а не другие объекты JSONB или значения et c.

Моя попытка:

do $$
declare
    colvar varchar;
begin
select x ->> 'ID' from (select jsonb_array_elements(f) from (
select (field ->>'protelUniqueID')::jsonb f
FROM guest_group gg,
lateral jsonb_array_elements(custom_fields) AS field
WHERE value @> '{"servicio_tags": ["protel-info"]}'::jsonb
) d(f)) dd(x) 
where x->>'ID_Context'='protelIO'
 into colvar;
    raise notice 'colvar: %', colvar;
end
$$;
execute format('UPDATE guest_group SET guest_profile_id = %s, colvar);

Мой результат: Это только берет Test1-ID и сохраняет его во всех строках в столбце guest_profile_id.

Моя проблема: Я хочу сохранить каждый TestX-ID в столбце custom_fields в столбце guest_profile_id в том же самом строка.

Мое предположение: Мне нужно добавить al oop к этому запросу. Если запрос там не находит никакого значения, l oop должен попробовать следующий запрос: например:

SELECT field ->>'value'
FROM guest_group gg
cross join lateral jsonb_array_elements(custom_fields) AS field
WHERE value @> '{"servicio_tags": ["profile-id"]}'::jsonb

А затем следующий:

SELECT field ->>'value'
FROM guest_group gg
cross join lateral jsonb_array_elements(custom_fields) AS field
WHERE value @> '{"servicio_tags": ["person-name"]}'::jsonb

Когда все TestX -ID значения копируются в столбец guest_profile_id в той же строке, цель достигнута.

Как я могу собрать все это вместе? Большое спасибо за помощь.

1 Ответ

1 голос
/ 10 апреля 2020

Я хочу сохранить каждый TestX-ID в столбце custom_fields в столбце guest_profile_id в той же строке.

Нет необходимости в PL / PG SQL, циклах или динамицах c sql. Просто используйте один запрос в форме

UPDATE guest_group
SET guest_profile_id = (/* complex expression */);

В вашем случае, с этим сложным выражением это составит

UPDATE guest_group
SET guest_profile_id = (
    SELECT x ->> 'ID'
    FROM jsonb_array_elements(custom_fields) AS field,
         jsonb_array_elements(field ->> 'protelUniqueID') AS dd(x)
    WHERE value @> '{"servicio_tags": ["protel-info"]}'::jsonb
      AND x->>'ID_Context' = 'protelIO'
);

Если запрос там не находит никакого значения , он должен попробовать следующий запрос

Вы можете использовать для этого функцию COALESCE, или добавить несколько OR условий к вашему запросу, или даже использовать UNION. Либо добавьте WHERE guest_profile_id IS NULL в оператор обновления, чтобы исключить те строки, которые уже имеют значение, и выполнить несколько последовательных обновлений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...