【问题标题】:How to add a default value to json_build_object postgresql如何将默认值添加到 json_build_object postgresql
【发布时间】:2021-08-16 14:55:03
【问题描述】:

我的 json 看起来像这样:-

{"DestinationLists": [{"name": "TVNZ, Mediaworks, Choice", "destinations": []}, { "name": "TVNZ, Discovery", "destinations": [165, 183, 4155]}]}

我想要的输出是数组中每个对象的一行,例如:-

{"name" : "TVNZ, Mediaworks, Choice", "destinations" : []}
{"name" : "TVNZ, Discovery", "destinations" : [{"Id" : 165}, {"Id" : 183}, {"Id" : 4155}]}

我的查询是这样的:-

WITH ExpandedData AS (
    SELECT
        "Id",
        setting,
        json_build_object(
            'name',
             dl->>'name',
             'destinations',
             json_agg(
               json_build_object('Id',dld::text::int)
             )
        ) as DestinationListItem
    FROM
        feature.settings, 
        jsonb_array_elements(value->'DestinationLists') dl,
        jsonb_array_elements(dl->'destinations') dld
    GROUP BY
        "Id",dl->>'name'
)
select * from ExpandedData

但是这个查询缺少destinations,其中数组为空,所以我从查询中得到的结果是:-

{"name" : "TVNZ, Discovery", "destinations" : [{"Id" : 165}, {"Id" : 183}, {"Id" : 4155}]}

只有一排而不是两排。如何更新此查询以获得所需的结果?

DBFiddle 在这里:- https://www.db-fiddle.com/f/tDA7SajDoWhXrQaAa1j2qN/0

编辑:我已经能够进一步深入研究我的问题,所以问题基本上是从查询的这一行发生的:-

jsonb_array_elements(dl->'destinations') dld

基本上,当destinations 数组为空时,jsonb_array_elements 不会返回任何内容,所以我猜这里正确的解决方案是在将一个空数组传递给它时以某种方式从jsonb_array_elements 返回一个空数组。

【问题讨论】:

  • 你能准备一个 DBfiddle 吗?
  • 嗨,用 DB fiddle @IVOGELOV 更新了我的问题
  • 这个answer 回答你的问题了吗?

标签: sql json postgresql


【解决方案1】:

你可以使用递归cte

with recursive cte(js, ind, r) as (
   select js, 1, case when json_array_length(js -> 'DestinationLists' -> 0 -> 'destinations') = 0 then (js -> 'DestinationLists' -> 0)::jsonb else jsonb_set(js::jsonb, concat('{DestinationLists,', 0, ',destinations}')::text[], (select array_to_json(array_agg(json_build_object('Id', value))) from json_array_elements(js -> 'DestinationLists' -> 0 -> 'destinations'))::jsonb) end from data
   union all
   select js, ind+1, case when json_array_length(js -> 'DestinationLists' -> ind -> 'destinations') = 0 then (js -> 'DestinationLists' -> ind)::jsonb else (jsonb_set(js::jsonb, concat('{DestinationLists,', ind, ',destinations}')::text[], (select array_to_json(array_agg(json_build_object('Id', value))) from json_array_elements(js -> 'DestinationLists' -> ind -> 'destinations'))::jsonb) -> 'DestinationLists' -> ind)::jsonb end from cte where ind < json_array_length(js -> 'DestinationLists')
)
select r from cte;

输出:

r
{"name": "TVNZ, Mediaworks, Choice", "destinations": []}
{"name": "TVNZ, Discovery", "destinations": [{"Id": 165}, {"Id": 183}, {"Id": 4155}]}

【讨论】:

  • 这对我来说有点太复杂了,我是第一次研究 postgresql。我在哪里可以将递归部分与我现有的查询相匹配?
  • @FakharAhmadRasul 本质上,您的ExpandedData cte 定义可以替换为我上面回答中的cte,而select * from ExpandedData 可以切换为select r from cte
  • @FakharAhmadRasul 另外,根据您的小提琴,列名js 可以替换为dest
  • 我已经更新了我的问题,您是否认为尝试从jsonb_array_elements 返回一个空数组以防它的输入也是一个空数组会是更好的方法?有可能吗?
猜你喜欢
  • 2012-08-09
  • 2021-09-10
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-28
  • 2022-08-04
  • 2013-09-29
相关资源
最近更新 更多