В предложении FROM имеется более одной строки для одной изменяемой строки. Документация объясняет это ясно:
При использовании FROM вы должны убедиться, что соединение создает не более одной выходной строки для каждой строки, подлежащей изменению. Другими словами, целевая строка не должна соединяться с более чем одной строкой из других таблиц. Если это так, то только одна из строк соединения будет использоваться для обновления целевой строки, но какая из них будет использоваться, трудно предсказать.
Вы можете выполнить одно обновление, сгруппировав ожидаемое значение в подзапросе. Используйте агрегатную функцию jsonb_object_agg()
:
update posts p
set a_to_b = agg
from (
select p.id, jsonb_object_agg(username, random()) as agg
from posts p
join reactions r on p.id = r.post_id
group by p.id
) s
where s.id = p.id;
SqlFiddle.
В качестве альтернативы, вы можете использовать блок анонимного кода , чтобы многократно обновлять одну строку, например ::
do $$
declare rec record;
begin
for rec in
select *
from posts p
join reactions r on p.id = r.post_id
loop
update posts
set a_to_b = jsonb_set(a_to_b, array[rec.username], to_jsonb(random()))
where posts.id = rec.post_id;
end loop;
end $$;
Второе решение может оказаться неоптимальным, особенно для большого количества агрегированных значений.