Dr_Elvis
@Dr_Elvis
В гугле забанен

Как правильно проапдейтить поле JSON?

Есть таблица с полями id, ticket_id, task_id, mycontent.
первые три поля - числа, последнее jsonb
на каждый ticket_id выводит две или больше строки с разным task_id.
нужно проапдейтить поле mycontent, изменив в json по определенному пути значение в виде "ticket_id:task_id", причем task_id должен быть минимальным из всех строк(по id), а изменения должны быть только в максимальном из всех строк(по id).
Пробовал как то так:
update myorders
set mycontent= jsonb_set(mycontent, '{orders, initialTaskId}', to_jsonb(concat(ticket_id, ':', (select min(xx.task_id) from myorders xx where xx.ticket_id=ticket_id))::text), false)
where id = (select t.id 
			from myorders t 
			where t.ticket_id=1792829 
			order by t.id desc 
			limit 1)

Однако в итоге в итоговом значении в task_id выбирается минимальный из всей таблицы(т.е. вид получается такой: "1792829:1", а должно "1792829:14709539"), а не из тех строк, что по условию.
Пример таблицы:
id    |ticket_id|task_id |mycontent                                      
------+---------+--------+-------------------------------------------------
106849|  1792829|14709539|{"orders": {"initialTaskId": "1792829:14709539"}}
108057|  1792829|14740625|{"orders": {"initialTaskId": null}}

Если выполнить типо такого, то выводит всё правильно:
select jsonb_set(mo.mycontent, '{orders, initialTaskId}', to_jsonb(concat(mo.ticket_id, ':', (select min(xx.task_id) from myorders xx where xx.ticket_id=mo.ticket_id))::text), false)
from myorders mo 
where mo.ticket_id = 1792829
order by mo.id desc
limit 1


Прошу помощи поправить скрипт UPDATE.
  • Вопрос задан
  • 111 просмотров
Решения вопроса 1
Dr_Elvis
@Dr_Elvis Автор вопроса
В гугле забанен
В итоге вопрос решился так:
DO $$
DECLARE
  arr int[] := array[1792829,1792830,1792831,1792832];
  x int;
BEGIN
  FOREACH x IN ARRAY arr
  LOOP
    update myorders
    set content = jsonb_set(content, '{orders, initialTaskId}', to_jsonb((select t.content #>> '{orders, initialTaskId}' from myorders t where t.id = (select min(t.id) from myorders t where t.ticket_id=x))::text), false)
    where id = (select max(t.id) from myorders t where t.ticket_id=x);
  END LOOP;
END;
$$
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@humoured
Вы всё на свете найдёте в коробке с карандашами
select max(t.id)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы