【问题标题】:Error with nested JSON self referencing result set 'aggregate function calls cannot be nested'嵌套 JSON 自引用结果集“不能嵌套聚合函数调用”时出错
【发布时间】:2018-10-19 12:58:32
【问题描述】:

我有以下数据架构

-- table
master 
 - id (int)
 - meta (jsonb)
 - key (string)

-- table
 details 
  - master_id (int)
  - timestamp (timestamp)
  - value     (float)

(简体)

以下查询因以下错误而终止:

select json_build_object(
    'name',m.meta->>'name',
    'keys',json_agg(
        json_build_object(
        'key',m.key,
        'checkpoints',json_agg(
            json_build_object(
            'time',d.timestamp,
            'value',d.value)
        )
        )
    )
)
from master m, details d 
GROUP by m.meta->>'name',m.key,d.timestamp,d.value


ERROR:  aggregate function calls cannot be nested
LINE 6:   'checkpoints',json_agg(

我想得到以下结构。

[
    {"name":"name",
     "keys":[
        {"key":"mykey",
            "checkpoints":[
                {"time":"timestamp","value":"1.2"},...]
        },...]
    }...
]

我知道这个错误是可以理解的,我不能使用嵌套的json_agg。但我不知道如何解决它。

此答案建议使用内联查询:PostgreSQL aggregate function calls cannot be nested using jsonb_agg function

但这对我也不起作用,或者我遗漏了一些东西。

感谢您对查询的帮助,

编辑// 提供了一个包含示例数据和工作结果的数据库小提琴,其中不包括每个传感器的检查点。

https://www.db-fiddle.com/f/2XaUFeTcTfFFUrPYsVnYkt/0

【问题讨论】:

  • 你能用一些示例数据创建一个 db fiddle 表吗?
  • @eurotrash 添加了 db fiddle

标签: postgresql postgresql-9.6 postgresql-json


【解决方案1】:

在进入查询之前,请注意我更改了连接条件。我认为在 id/master_id 上加入 details 是准确的,因为您在 dbfiddle 中的原始查询似乎没有返回正确的结果;当您在details 中只有两条 id 为 1 的记录时,您真的想要{"name":"x32Z72","keys":[{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"}]} 吗?


这里有两个选项:

1:不要加入主查询,而是在details 上执行子查询以获取每个键的检查点。子查询独立存在,因此没有嵌套的 agg 调用问题。

SELECT json_build_object(
    'name', meta->>'name',
    'keys', json_agg(
        json_build_object(
            'key', key,
            'checkpoints', (
                SELECT json_agg(
                    json_build_object(
                        'time', d.timestamp,
                        'value', d.value
                    )
                )
                FROM details d
                WHERE master_id = m.id
                GROUP BY master_id
            )
        )
    )
)
FROM masters m
GROUP by m.meta->>'name', m.key

https://www.db-fiddle.com/f/2XaUFeTcTfFFUrPYsVnYkt/1

2:进行连接,但在不同级别上进行聚合。所以首先在最低/最内层(检查点)上做一个 agg,然后你有一个外部选择来做更高级别的 agg(键):

SELECT json_build_object(
    'name', name,
    'keys', json_agg(
        json_build_object(
            'key', key,
            'checkpoints', checkpoints
        )
    )
)
FROM (
    SELECT
        m.meta->>'name' AS name,
        m.key,
        json_agg(
            json_build_object(
                'time', d.timestamp,
                'value', d.value
            )
        ) AS checkpoints
    FROM masters m
    INNER JOIN details d ON m.id = d.master_id
    GROUP by m.meta->>'name', m.key, d.master_id
) s
GROUP BY name, key

https://www.db-fiddle.com/f/2XaUFeTcTfFFUrPYsVnYkt/2

无论哪种情况,结果都是一样的:

{"name":"x32Z72","keys":[{"key":"sensor1","checkpoints":[{"time":"2018-10-03T00:00:00+00:00","value":1},{"time":"2018-10-03T01:01:12+00:00","value":1.5},{"time":"2018-10-03T00:10:00+00:00","value":2.1}]}]}
{"name":"x32Z72","keys":[{"key":"sensor2","checkpoints":[{"time":"2018-10-03T02:12:01+00:00","value":0.8},{"time":"2018-10-03T06:10:00+00:00","value":1.8}]}]}
{"name":"x32Z72","keys":[{"key":"sensor3","checkpoints":[{"time":"2018-10-03T01:01:12+00:00","value":0.95}]}]}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-29
    相关资源
    最近更新 更多