嵌套 JSON 自引用结果集 'aggregate function calls cannot be nested' 出错
Error with nested JSON self referencing result set 'aggregate function calls cannot be nested'
我有以下数据模式
-- 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
嵌套。但我不知道如何解决。
此答案建议使用内联查询:
但这对我也不起作用,或者我遗漏了一些东西。
不胜感激,
编辑//
提供了一个带有示例数据和工作结果的数据库 fiddle,其中不包括每个传感器的检查点。
在开始查询之前,请注意我更改了连接条件。我假设在 id/master_id 上加入 details
是准确的,因为你在 dbfiddle 中的原始查询似乎 return 没有正确的结果;当您在 details
中只有两条 ID 为 1 的记录时,您真的想要 {"name":"x32Z72","keys":[{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"}]}
吗?
这里有两个选项:
1:不要加入主查询,而是在 details
上执行子查询以获取每个键的检查点。子查询独立存在,因此不存在嵌套聚合调用问题。
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:进行连接,但在不同级别进行聚合。所以首先在 lowest/innermost 级别(检查点)上做一个聚合,然后你有一个外部 select 来做更高级别的聚合(键):
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}]}]}
我有以下数据模式
-- 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
嵌套。但我不知道如何解决。
此答案建议使用内联查询:
但这对我也不起作用,或者我遗漏了一些东西。
不胜感激,
编辑// 提供了一个带有示例数据和工作结果的数据库 fiddle,其中不包括每个传感器的检查点。
在开始查询之前,请注意我更改了连接条件。我假设在 id/master_id 上加入 details
是准确的,因为你在 dbfiddle 中的原始查询似乎 return 没有正确的结果;当您在 details
中只有两条 ID 为 1 的记录时,您真的想要 {"name":"x32Z72","keys":[{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"}]}
吗?
这里有两个选项:
1:不要加入主查询,而是在 details
上执行子查询以获取每个键的检查点。子查询独立存在,因此不存在嵌套聚合调用问题。
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:进行连接,但在不同级别进行聚合。所以首先在 lowest/innermost 级别(检查点)上做一个聚合,然后你有一个外部 select 来做更高级别的聚合(键):
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}]}]}