Версия, которая работает с CockroachDB (протестирована с v2.1.5):
CREATE TABLE test_data (
id serial primary key,
data jsonb not null
);
INSERT INTO test_data (data) VALUES
('[[{"speaker":null,"start":0.02,"stop":2.25,"text":"random text 123"},{"speaker":null,"start":291.45,"stop":291.88,"text":"random text 123"},{"speaker":null,"start":292.07,"stop":293.63,"text":"random text 123"}],[]]'::jsonb),
('[[{"speaker":null,"start":0.05,"stop":1.97,"text":"random text 123"},{"speaker":null,"start":260.78,"stop":261.23,"text":"random text 123"},{"speaker":null,"start":272.07,"stop":273.73,"text":"random text 123"}],[]]'::jsonb)
;
SELECT test_data.id,
sum((items.item->>'stop')::numeric - (items.item->>'start')::numeric)
FROM test_data
INNER JOIN (SELECT id, jsonb_array_elements(data#>'{0}'::string[]) AS item FROM test_data) AS items ON (items.id = test_data.id)
GROUP BY 1
ORDER BY 1;
... в результате:
id | sum
+--------------------+------+
432708358512836609 | 4.22
432708358512869377 | 4.03
(2 rows)
Объяснено:
tree | field | description
+---------------------------------+-------------+-------------------+
sort | |
│ | order | +id
└── group | |
│ | aggregate 0 | id
│ | aggregate 1 | sum(column6)
│ | group by | @2
└── render | |
└── join | |
│ | type | inner
│ | equality | (id) = (id)
├── project set | |
│ └── scan | |
│ | table | test_data@primary
│ | spans | ALL
└── scan | |
| table | test_data@primary
| spans | ALL
(17 rows)
При полной поддержке PostgreSQL вы можете использовать LATERAL
объединений и GROUP BY ROLLUP
, чтобы также получить общую сумму:
SELECT id, sum((items->'stop')::numeric - (items->'start')::numeric)
FROM test_data, LATERAL jsonb_array_elements(data#>'{0}') AS items
GROUP BY rollup(1)
ORDER BY 1 NULLS LAST;
... результат:
id | sum
----+------
1 | 4.22
2 | 4.03
| 8.25
(3 rows)
Объяснил (на самом деле проще, чем в CockroachDB из-за отсутствия объединения и сортировки по индексу):
QUERY PLAN
-------------------------------------------------------------------------------------------------
GroupAggregate (cost=0.16..4815.59 rows=1271 width=36)
Group Key: test_data.id
Group Key: ()
-> Nested Loop (cost=0.16..2577.21 rows=127000 width=36)
-> Index Scan using test_data_pkey on test_data (cost=0.15..37.20 rows=1270 width=36)
-> Function Scan on jsonb_array_elements items (cost=0.01..1.00 rows=100 width=32)
(6 rows)