Postgres从宽列设计到关键值构建复杂的JSON对象

时间:2017-11-07 08:47:49

标签: sql json postgresql jsonb

在我脑海爆炸之前,我真的可以在这里使用一些帮助...... 鉴于以下数据结构:

SELECT * FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange);

 day | apple | banana | orange 
-----+-------+--------+--------
   1 |     1 |      1 |      1
   2 |     2 |      2 |      2

我想构建一个JSON对象,如下所示:

{
  "data": [
    {
      "day": 1,
      "fruits": [
        {
          "key": "apple",
          "value": 1
        },
        {
          "key": "banana",
          "value": 1
        },
        {
          "key": "orange",
          "value": 1
        }
      ]
    }
  ]
}

也许我离目标不远:

SELECT json_build_object(
  'data', json_agg(
    json_build_object(
      'day', t.day,
      'fruits', t)
    )
) FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange);

结果:

{
  "data": [
    {
      "day": 1,
      "fruits": {
        "day": 1,
        "apple": 1,
        "banana": 1,
        "orange": 1
      }
    }
  ]
}

我知道有json_each可以解决问题。但我正在努力将其应用于查询。

修改 : 这是我更新的查询,我猜,它非常接近。我放弃了用json_each解决问题的想法。现在我只需要返回一个fruits数组,而不是附加到fruits对象:

SELECT json_build_object(
    'data', json_agg(
        json_build_object(
            'day', t.day,
            'fruits', json_build_object(
                'key', 'apple', 
                'value', t.apple, 
                'key', 'banana', 
                'value', t.banana, 
                'key', 'orange', 
                'value', t.orange
            )
        )
    )
) FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange);

我是否需要添加子查询以防止嵌套聚合函数?

1 个答案:

答案 0 :(得分:3)

使用函数jsonb_each()获取对(key, value),,这样您无需知道列数及其名称即可获得正确的输出:

select jsonb_build_object('data', jsonb_agg(to_jsonb(s) order by day))
from (
    select day, jsonb_agg(jsonb_build_object('key', key, 'value', value)) as fruits
    from (
        values (1, 1, 1, 1), (2, 2, 2, 2)
    ) as t(day, apple, banana, orange),
    jsonb_each(to_jsonb(t)- 'day')
    group by 1
    ) s;

上面的查询给出了这个对象:

{
    "data": [
        {
            "day": 1,
            "fruits": [
                {
                    "key": "apple",
                    "value": 1
                },
                {
                    "key": "banana",
                    "value": 1
                },
                {
                    "key": "orange",
                    "value": 1
                }
            ]
        },
        {
            "day": 2,
            "fruits": [
                {
                    "key": "apple",
                    "value": 2
                },
                {
                    "key": "banana",
                    "value": 2
                },
                {
                    "key": "orange",
                    "value": 2
                }
            ]
        }
    ]
}