Explicação
A subseleção no
FROM
cláusula do seu UPDATE
retorna três linhas. Mas cada linha na tabela de destino só pode ser atualizada uma vez em um único UPDATE
comando. O resultado é que você só vê o efeito de um dessas três linhas. Ou, nas palavras do manual :
A parte:não chame sua subconsulta de "cte". Não é uma Expressão de tabela comum .
UPDATE
adequada
UPDATE table_ t
SET value_ = jsonb_set(value_, '{iProps}', sub2.new_prop, false)
FROM (
SELECT id
, jsonb_agg(jsonb_set(prop, '{value, rules}', new_rules, false)
ORDER BY idx1) AS new_prop
FROM (
SELECT t.id, arr1.prop, arr1.idx1
, jsonb_agg(jsonb_set(rule, '{ao,sc}', rule #> '{ao,sc,name}', false)
ORDER BY idx2) AS new_rules
FROM table_ t
, jsonb_array_elements(value_->'iProps') WITH ORDINALITY arr1(prop,idx1)
, jsonb_array_elements(prop->'value'->'rules') WITH ORDINALITY arr2(rule,idx2)
GROUP BY t.id, arr1.prop, arr1.idx1
) sub1
GROUP BY id
) sub2
WHERE t.id = sub2.id;
db<>fiddle aqui
Use
jsonb_set()
em cada objeto (elemento de array) antes de agregá-los de volta em um array. Primeiro no nível da folha, e novamente no nível mais profundo. Eu adicionei
id
como PRIMARY KEY
para a mesa. Precisamos de alguma coluna exclusiva para manter as linhas separadas. O
ORDER BY
adicionado pode ou não ser necessária. Adicionado para garantir o pedido original. Obviamente, se seus dados forem tão regulares quanto a amostra, um design relacional com colunas dedicadas pode ser uma alternativa mais simples. Ver