![](/img/trans.png)
[英]Update object field of element in array jsonb with postgres
[英]Update partial jsonb field in Postgres 13
任何人都可以幫助優化 SQL 請求 Postgres 13 (jsonb)。
需要用指定的 ID 更新 Jsonb 字段內的“百分比”值
此示例正在運行,但它在大型數據庫上運行了很長時間。
select version();
CREATE TABLE collection (
ID serial NOT NULL PRIMARY KEY,
info jsonb NOT NULL
);
INSERT INTO collection (info)
VALUES
(
'[{"id": "1", "percent": "1"}, {"id": "6", "percent": "2"}]'
),
(
'[{"id": "5", "percent": "3"}, {"id": "1", "percent": "4"}]'
),
(
'[{"id": "1", "percent": "5"}, {"id": "2", "percent": "5"}, {"id": "3", "percent": "5"}]'
);
UPDATE collection
SET info = array_to_json(ARRAY(SELECT jsonb_set(x.original_info,
'{percent}',
(
CASE
WHEN x.original_info ->> 'id' = '1'
THEN '25'
ELSE
concat('"',
x.original_info ->> 'percent',
'"')
END
)::jsonb)
FROM (SELECT jsonb_array_elements(collection.info) original_info) x))::jsonb;
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=a521fee551f2cdf8b189ef0c0191b730
我將其表述為:
update collection c
set info = (
select jsonb_agg(
case when obj ->> 'id' = '1'
then x.obj - '{percent}' || '{"percent": "25"}'
else x.obj
end
order by x.rn
)
from jsonb_array_elements(c.info) with ordinality as x(obj, rn)
)
邏輯與原始代碼中的邏輯完全相同,但這會跳過一些不必要的強制轉換,並使用直接 json 數組聚合而不是中間數組轉換。 另外,我使用了 json 運算符而不是jsonb_set()
。
另一個重要的一點是,這保留了原始 json 數組中對象的順序 - 而您的原始代碼沒有。
如果表中有很多行沒有 object 有您搜索的 id,那么我們可以預先過濾數據以僅更新相關行。 為此,您可以執行以下操作:
update collection c
set info = c1.info
from (
select c.id,
jsonb_agg(
case when obj ->> 'id' = '1'
then x.obj - '{percent}' || '{"percent": "25"}'
else x.obj
end
order by x.rn
) as info
from collection c
cross join lateral jsonb_array_elements(c.info) with ordinality as x(obj, rn)
group by c.id
having bool_or(obj ->> 'id' = '1' )
) c1
where c1.id = c.id
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.