LINUX.ORG.RU

Подсчитать сумму элементов jsonb

 ,


0

1

Использую PGSQL.

Есть 2 поля в таблице One(jsonb), Two(jsonb)

каждое поле всегда состоят из 3 jsonb элементов

Пример:
One: [{'А': 10, 'B': 5},{'C': 6},{'D': 1}]
Two: [{'A_1': 'A_2', 'A_3': 'A_4'}, {'B_1': 'B_2'}, {'D_1': 'D_2'}]

Для поля One нужно посчитать сумму всех элементах во всех 3 jsonb для примера выше сумма будет 10+5+6+1=22.

Для поля Two нужно посчитать количество всех ключей во всех 3 json для примера выше количество будет 4.

Написал такой запрос

select 
	(
		select sum(v::int) from jsonb_each("One"[0] || "One"[1] || "One"[2]) AS x(k, v)
		where  jsonb_typeof(v) = 'number'  
	) as "sum_jsonb",
	(
		select count(*) from jsonb_object_keys("Two"[0] || "Two"[1] || "Two"[2]) 
	) as "count_jsonb"
from T

Проблема возникла, что запрос не выполняется на PGSQL 10 и ниже, в нем нельзя обращаться к jsonb по индексу «One»[0].

Просьба помочь, как проще написать данный запрос, чтобы можно было выполнить на старой версии PGSQL

Что-то типа

SELECT 
    (
        SELECT SUM((elem->>key)::int) 
        FROM (
            SELECT jsonb_each(value) 
            FROM (
                SELECT jsonb_array_elements("One") AS value
            ) AS array_elements
        ) AS elem
        WHERE jsonb_typeof(elem.value) = 'number'
        CROSS JOIN LATERAL jsonb_object_keys(value) AS key
    ) AS sum_jsonb,
    
    (
        SELECT COUNT(*)
        FROM (
            SELECT jsonb_each(value) 
            FROM (
                SELECT jsonb_array_elements("Two") AS value
            ) AS array_elements
        ) AS elem
    ) AS count_jsonb
FROM T;

?

Нет базы по рукой с такой версией, могут быть ошибки

PPP328 ★★★★★
()
Последнее исправление: PPP328 (всего исправлений: 1)
SELECT
	 s1.one_sum
	,s2.two_count
FROM
	"T" t
	CROSS JOIN LATERAL (
		SELECT sum((x.n::text)::int) FILTER(WHERE jsonb_typeof(x.n) = 'number') AS one_sum
		FROM (
			SELECT (jsonb_each(j.value)).value AS n FROM jsonb_array_elements(t."One") j
		) x
	) s1
	CROSS JOIN LATERAL (
		SELECT sum(x.k) AS two_count
		FROM (
			SELECT count(*) AS k FROM (SELECT jsonb_object_keys(j.value) FROM jsonb_array_elements(t."Two") j) jj
		) x
	) s2
;

Проверил на 9.4

Он еще и кастовать jsonb сразу в int не умеет, только через text.

Toxo2 ★★★★
()