W.r.t。下面的函数,我希望在执行 select 查询时调用此函数来操作 json 类型的列。
CREATE OR REPLACE FUNCTION apply_foreign_exchange(input_value json, conversion_rate NUMERIC(14,10)) RETURNS json AS $$
DECLARE price_tier json;
BEGIN
IF input_value is not null THEN
FOR price_tier IN SELECT * FROM json_array_elements(input_value)
LOOP
if price_tier->>'amount' is not null THEN
price_tier->>'amount' = price_tier->>'amount' * conversion_rate ;
end if;
END LOOP;
end if;
return input_value;
END; $$
LANGUAGE plpgsql;
我的 input_value 与此非常相似:
'[{"untilQuantity":600,"amount":999},{"untilQuantity":800,"amount":99},{"amount":9}]'
conversion_rate 为 1.5
我想要以下格式的输出
'[{"untilQuantity":600,"amount":1498.5},{"untilQuantity":800,"amount":148.5},{"amount":13.5}]'
看来我做不到
price_tier->>'amount' = price_tier->>'amount' * conversion_rate ;
最后这个函数将被类似的东西调用
Select
.......,
apply_foreign_exchange(chrg.price_tiers, currency_conversion.conversion_rate) AS "Charge Price Tiers",
......
from <>;
我会分解 JSON,执行计算,然后重新组装对象数组:
CREATE OR REPLACE FUNCTION apply_foreign_exchange(input_value jsonb, conversion_rate NUMERIC(14,10))
RETURNS jsonb AS $$
with exploded as (
select i, k,
case
when k = 'amount' then (v::decimal(10,2) * 1.5)::text
else v
end as v
from jsonb_array_elements(input_value) with ordinality as el(obj, i)
cross join lateral jsonb_each_text(el.obj) as ea(k, v)
), group_objs as (
select i, jsonb_object_agg(k, v) as obj
from exploded
group by i
)
select jsonb_agg(obj order by i)
from group_objs
;
$$
LANGUAGE sql;