Uitleg
De subselect in de FROM
clausule van uw UPDATE
retourneert drie rijen. Maar elke rij in de doeltabel kan slechts één keer worden bijgewerkt in een enkele UPDATE
opdracht. Het resultaat is dat je slechts het effect ziet van één van die drie rijen.
Of, in de woorden van de handleiding :
Terzijde:noem je subquery niet "cte". Het is geen Algemene tabeluitdrukking .
Juiste UPDATE
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 hier
Gebruik jsonb_set()
op elk object (array-element) voordat ze weer worden samengevoegd tot een array. Eerst op het bladniveau en opnieuw op het diepere niveau.
Ik heb id
toegevoegd als PRIMARY KEY
Naar de tafel. We hebben een unieke kolom nodig om de rijen gescheiden te houden.
De toegevoegde ORDER BY
al dan niet vereist zijn. Toegevoegd om de originele bestelling te garanderen.
Als uw gegevens net zo regelmatig zijn als het voorbeeld, kan een relationeel ontwerp met speciale kolommen natuurlijk een eenvoudiger alternatief zijn. Zie