【问题标题】:Postgresql update record column based on it's JSONB field values sumPostgresql 更新记录列基于它的 JSONB 字段值总和
【发布时间】:2018-06-20 22:03:05
【问题描述】:

我在 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 中使用聚合函数的错误。

我尝试这样做:

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

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

【问题讨论】:

    标签: sql json postgresql jsonb


    【解决方案1】:

    返回 fn() 聚合的集合尝试:

    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;
    

    错误:

    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.
    

    很容易被另一个 cte 克服:

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

    所以现在只需从 CTE 更新:

    with s as (SELECT ((jsonb_array_elements(data::jsonb->'CheckClose'->'Payments')->>'Amount')::FLOAT) AS "sm", id
        FROM test
    )
    , a as (select sum(sm), id from s group by id)
    UPDATE test SET amount = sum
    FROM a
    WHERE id=test.id
    

    【讨论】:

    • 能否提供完整的更新查询?我对这些东西很陌生...尝试这样做:@ 987654325@,但它在所有金额字段中写入了一些巨大的价值,都是一样的...
    猜你喜欢
    • 2021-02-12
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 2019-04-24
    • 1970-01-01
    相关资源
    最近更新 更多