powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Агрегировать json
5 сообщений из 5, страница 1 из 1
Агрегировать json
    #39340891
kotahinus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Помогите пожалуйста решить задачу.

Есть множество json'ов типа

Код: plsql
1.
2.
3.
{ "1" : 2, "2" : 5, "3" : 10 }
{ "1" : 1, "3" : 7 }
{ "1" : 8, "2" : 1, "3" : 12 }



И нужно слить их в один складывая элементы с соответствующими индексами.

Код: plsql
1.
{ "1" : 11, "2" : 6, "3" : 29 }



Я написал агрегатную функцию json2json и в SFUNC вписал вот такой json_sum

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
BEGIN
	RETURN
	(
		SELECT json_object_agg(t.key, t.count) AS res FROM
		(
			SELECT w.key, SUM(CASE WHEN w.value IS NULL THEN 0 ELSE (w.value::int) END) AS count FROM (
				SELECT key, value FROM json_each_text($1)
				UNION
				SELECT key, value FROM json_each_text($2)
			) w GROUP BY key
		) t
	);
END



Оно считает все почти правильно. Погрешность невелика но от нее надо избавиться. Вот такой пример использования выдаст различные результаты при суммировании json'а функцией и отдельных полей.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
SELECT
	json2json(json_row),
	SUM((json_row->>'1')::int) AS a1,
	SUM((json_row->>'2')::int) AS a2,
	SUM((json_row->>'3')::int) AS a3
FROM
	t



В чем может быть здесь загвоздка? Или вдруг у вас есть какие-то другие наработки которые могли бы помочь решить данную задачу?
...
Рейтинг: 0 / 0
Агрегировать json
    #39342448
kotahinus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кажется я докопался до сути)))

Код: plsql
1.
2.
3.
SELECT key, value FROM json_each_text('{ "1" : 135, "3" : 34 }')
UNION
SELECT key, value FROM json_each_text('{ "1" : 132, "3" : 35 }')


возвращает
Код: plsql
1.
2.
3.
4.
5.
6.
 key | value 
-----+-------
 1   | 132
 3   | 34
 3   | 35
 1   | 135


,
а если так
Код: plsql
1.
2.
3.
SELECT key, value FROM json_each_text('{ "1" : 135, "3" : 34 }')
UNION
SELECT key, value FROM json_each_text('{ "1" : 132, "3" : 34 }')


то
Код: plsql
1.
2.
3.
4.
5.
 key | value 
-----+-------
 1   | 132
 3   | 34
 1   | 135



Из-за этого иногда и возникали погрешности.
...
Рейтинг: 0 / 0
Агрегировать json
    #39342453
kotahinus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Соответственно UNION ALL вместо UNION, кому понадобится.
...
Рейтинг: 0 / 0
Агрегировать json
    #39343139
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kotahinus, попробовал решить вашу задачу:
Код: sql
1.
2.
3.
4.
5.
6.
with j(t) as (values ( 
'{ "1" : 2, "2" : 5, "3" : 10 }'::json),
('{ "1" : 1, "3" : 7 }'),
('{ "1" : 8, "2" : 1, "3" : 12 }')
)
select json_agg(json_build_object(k, v)) from (SELECT k, sum(v) as v FROM j join lateral (select key as k, value::int as v from json_each_text(t) k)k on true group by 1)t


результат: [{"2" : 6}, {"3" : 29}, {"1" : 11}]
...
Рейтинг: 0 / 0
Агрегировать json
    #39343144
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
with j(t) as (values ( 
'{ "1" : 2, "2" : 5, "3" : 10 }'::json),
('{ "1" : 1, "3" : 7 }'),
('{ "1" : 8, "2" : 1, "3" : 12 }')
)
select json_agg(json_build_object(k, v) order by k) from (SELECT k, sum(v) as v FROM j join lateral (select key as k, value::int as v from json_each_text(t) k)k on true group by 1)t

если принципиально то здесь все ключи в порядке возрастания:
Код: sql
1.
[{"1" : 11}, {"2" : 6}, {"3" : 29}]
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Агрегировать json
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]