Ошибка с вложенным набором результатов JSON с самоссылкой «вызовы агрегатных функций не могут быть вложены» - PullRequest
0 голосов
/ 19 октября 2018

У меня следующая схема данных

-- 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 не могут быть вложены с помощью функции jsonb_agg

, но у меня это тоже не работает или я что-то упустил.

Была бы признательна за помощь в запросе,

EDIT // Предоставил скриптовую базу данных с примерами данных и рабочими результатами, которые еще не включают контрольную точку для каждого датчика.

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

1 Ответ

0 голосов
/ 20 октября 2018

Прежде чем перейти к запросам, обратите внимание, что я изменил условия соединения.Я полагаю, что правильно присоединиться к details для id / master_id, потому что ваш исходный запрос в dbfiddle, похоже, не дал правильных результатов;Вы действительно хотите {"name":"x32Z72","keys":[{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"},{"key":"sensor1"}]}, когда у вас есть только две записи в details с идентификатором 1?


Вот два варианта:

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: выполнять объединение, но выполнять аггирование на разных уровнях.Поэтому сначала выполните агг на самом нижнем / самом внутреннем уровне (контрольные точки), затем у вас есть внешний выбор, чтобы сделать агг более высокого уровня (клавиши):

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}]}]}
...