Explication
La sous-sélection dans le FROM
clause de votre UPDATE
renvoie trois Lignes. Mais chaque ligne de la table cible ne peut être mise à jour qu'une fois en une seule UPDATE
commande. Le résultat est que vous ne voyez que l'effet de un de ces trois lignes.
Ou, selon les termes de le manuel :
A part:n'appelez pas votre sous-requête "cte". Ce n'est pas une expression de table commune .
Bonne 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<>violon ici
Utilisez jsonb_set()
sur chaque objet (élément de tableau) avant de les agréger dans un tableau. D'abord au niveau des feuilles, puis de nouveau au niveau plus profond.
J'ai ajouté id
comme PRIMARY KEY
à la table. Nous avons besoin d'une colonne unique pour séparer les lignes.
Le ORDER BY
ajouté peut être nécessaire ou non. Ajouté pour garantir la commande d'origine.
Bien sûr, si vos données sont aussi régulières que l'échantillon, une conception relationnelle avec des colonnes dédiées peut être une alternative plus simple. Voir