在 postgressql 中使用 fucntion 执行选择查询时操作数据类型 json 的列

问题描述 投票:0回答:1

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 <>;
postgresql
1个回答
0
投票

我会分解 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;

工作小提琴

© www.soinside.com 2019 - 2024. All rights reserved.