1

给定以下两个表列jsonb类型:

股息实际

{
  "dividends": [
    {
      "amount": "2.9800",
      "balanceDate": "2020-06-30T00:00:00Z"
    },
    {
      "amount": "4.3100",
      "balanceDate": "2019-06-30T00:00:00Z"
    }
  ],
  "lastUpdated": "2020-11-16T14:50:51.289649512Z",
  "providerUpdateDate": "2020-11-16T00:00:00Z"
}

股息预测

{
  "dividends": [
    {
      "amount": "2.3035",
      "balanceDate": "2021-06-01T00:00:00Z"
    },
    {
      "amount": "3.0452",
      "balanceDate": "2022-06-01T00:00:00Z"
    },
    {
      "amount": "3.1845",
      "balanceDate": "2023-06-01T00:00:00Z"
    }
  ],
  "lastForecasted": "2020-11-13T00:00:00Z",
  "providerUpdateDate": "2020-11-16T00:00:00Z"
}

我想合并来自and的两个dividends数组,但在合并它们之前,我想在每个对象上添加一个额外的字段 ()。dividend_actualdividend_forecastforecast

我确实尝试了以下方法:

SELECT
    dividends
FROM
    stock_financial AS f
    INNER JOIN instrument AS i ON i.id = f.instrument_id,
    jsonb_array_elements(
        (f.dividend_forecast->'dividends' || jsonb '{"forecast": true}') || 
        (f.dividend_actual->'dividends' || jsonb '{"forecast": false}')
    ) AS dividends
WHERE
    i.symbol = 'ASX_CBA'
ORDER BY
    dividends ->>'balanceDate' DESC;

上面的查询给了我以下结果:

{"forecast":true}
{"forecast":false}
{"amount":"3.1845","balanceDate":"2023-06-01T00:00:00Z"}
{"amount":"3.0452","balanceDate":"2022-06-01T00:00:00Z"}
{"amount":"2.3035","balanceDate":"2021-06-01T00:00:00Z"}
{"amount":"2.9800","balanceDate":"2020-06-30T00:00:00Z"}
{"amount":"4.3100","balanceDate":"2019-06-30T00:00:00Z"}

但我需要的是以下输出:

{"amount":"3.1845","balanceDate":"2023-06-01T00:00:00Z","forecast":true}
{"amount":"3.0452","balanceDate":"2022-06-01T00:00:00Z","forecast":true}
{"amount":"2.3035","balanceDate":"2021-06-01T00:00:00Z","forecast":true}
{"amount":"2.9800","balanceDate":"2020-06-30T00:00:00Z","forecast":false}
{"amount":"4.3100","balanceDate":"2019-06-30T00:00:00Z","forecast":false}
4

1 回答 1

2

事实证明,默认情况下,不可能在单个操作中更新 json 数组中的多个 jsons 对象。

为了能够做到这一点,Postgres function需要创建一个:

-- the params are the same as in aforementioned `jsonb_set`
CREATE OR REPLACE FUNCTION update_json_array_elements(target jsonb, path text[], new_value jsonb)
  RETURNS jsonb language sql AS $$
    -- aggregate the jsonb from parts created in LATERAL
    SELECT jsonb_agg(updated_jsonb)
    -- split the target array to individual objects...
    FROM jsonb_array_elements(target) individual_object,
    -- operate on each object and apply jsonb_set to it. The results are aggregated in SELECT
    LATERAL jsonb_set(individual_object, path, new_value) updated_jsonb
  $$;

kubak在这个答案 中建议了上述功能: https ://stackoverflow.com/a/53712268/782390

结合这个查询:

SELECT
    dividends
FROM
    stock_financial AS f
    INNER JOIN instrument AS i ON i.id = f.instrument_id,
    jsonb_array_elements(
        update_json_array_elements(f.dividend_forecast->'dividends', '{forecast}', 'true') ||
        update_json_array_elements(f.dividend_actual->'dividends', '{forecast}', 'false')
    ) AS dividends
WHERE
    i.symbol = 'ASX_CBA'
ORDER BY
    dividends ->>'balanceDate' DESC;

然后我得到以下输出,这正是我需要的:

{"amount":"3.1845","forecast":true,"balanceDate":"2023-06-01T00:00:00Z"}
{"amount":"3.0452","forecast":true,"balanceDate":"2022-06-01T00:00:00Z"}
{"amount":"2.3035","forecast":true,"balanceDate":"2021-06-01T00:00:00Z"}
{"amount":"2.9800","forecast":false,"balanceDate":"2020-06-30T00:00:00Z"}
{"amount":"4.3100","forecast":false,"balanceDate":"2019-06-30T00:00:00Z"}
于 2020-11-20T00:49:48.263 回答