Postgresql更新记录列基于它的JSONB字段值总和

时间:2018-01-11 14:27:54

标签: sql json postgresql jsonb

我在Postgresql 9.6.5 中有一个表格,其中包含以下字段:

CREATE TABLE test (
  id SERIAL,
  data JSONB,
  amount DOUBLE PRECESION,
  PRIMARY KEY(id)
);

data列中有像这样的json对象:

{
"Type": 1,
  "CheckClose":
    {"Payments":
      [
        {"Type": 4, "Amount": 2068.07},
        {"Type": 1, "Amount": 1421.07}
      ]
    }
}

我需要做的是将每个行的amount字段输入Amount字段的Payments字段的余量data对象。例如,对于此特定对象,应该有2068.07 + 1421.07 = 3489.14 。 我已经阅读了一些关于Postgres json和jsonb函数的内容,所以我现在就在这里:

UPDATE test SET amount=sum((jsonb_array_elements(data::jsonb->'CheckClose'->'Payments')->>'Amount')::FLOAT)

那是行不通的 - 我在UPDATE中没有使用agregate函数时收到错误。

我尝试这样做:

UPDATE test SET amount=temp.sum
  FROM (
     SELECT sum((jsonb_array_elements(data::jsonb->'CheckClose'->'Payments')->>'Amount')::FLOAT) AS "sum"
    FROM test WHERE id=test.id
  ) as "temp"

现在我收到错误set-valued function called in context that cannot accept a set

我该怎么做?我只需要计算总和并将其放入另一行,这是一项如此艰巨的任务吗? 请任何人帮我解决这个问题。感谢。

1 个答案:

答案 0 :(得分:2)

set返回fn()聚合尝试:

A

错误:

B

很容易被另一个cte克服:

t=# with c(j) as (values('{"Payments":
      [
        {"Type": 4, "Amount": 2068.07},
        {"Type": 1, "Amount": 1421.07}
      ]
    }'::jsonb))
select sum((jsonb_array_elements(j->'Payments')->>'Amount')::float) from c;

现在只需从CTE更新:

ERROR:  aggregate function calls cannot contain set-returning function calls
LINE 7: select sum((jsonb_array_elements(j->'Payments')->>'Amount'):...
                    ^
HINT:  You might be able to move the set-returning function into a LATERAL FROM item.