Eu tenho esta tabela de onde estou executando uma consulta:
CREATE TABLE IF NOT EXISTS public.preprocess_things
(
preprocess_id integer NOT NULL DEFAULT nextval('preprocess_things_preprocess_id_seq'::regclass),
arrive_date date NOT NULL,
arrive_location character varying COLLATE pg_catalog."default" NOT NULL,
data jsonb NOT NULL,
CONSTRAINT preprocess_things_pkey PRIMARY KEY (preprocess_id),
CONSTRAINT preprocess_things_arrive_date_arrive_location_bo_key UNIQUE (arrive_date, arrive_location)
)
A consulta que estou executando é esta:
SELECT DATE_TRUNC('month', arrive_date) AS grouped_date,
LOWER(arrive_location) AS location,
json_build_object(
'1', SUM((data->'1')::int),
'2', SUM((data->'2')::int),
'3', SUM((data->'3')::int),
'4', SUM((data->'4')::int),
'5', SUM((data->'5')::int)
) AS data
FROM preprocess_things
GROUP BY grouped_date,
location
O resultado atual é:
data_agrupada | localização | dados |
---|---|---|
01-06-2018 00:00:00 | localização_00 | {"1": 1, "2": nulo, "3": nulo, "4": 1, "5": 8} |
01-05-2018 00:00:00 | localização_00 | {"1": nulo, "2": 9, "3": 10, "4": 8, "5": 3} |
Gostaria de aplicar outro SELECT, que adiciona uma linha para cada par de valores que não possui valor nulo, onde a chave vai para a coluna thing_type e o valor vai para a coluna total; assim:
data_agrupada | localização | tipo_coisa | total |
---|---|---|---|
01-06-2018 00:00:00 | localização_00 | 1 | 1 |
01-06-2018 00:00:00 | localização_00 | 4 | 1 |
01-06-2018 00:00:00 | localização_00 | 5 | 8 |
01-05-2018 00:00:00 | localização_00 | 2 | 9 |
01-05-2018 00:00:00 | localização_00 | 3 | 10 |
01-05-2018 00:00:00 | localização_00 | 4 | 8 |
01-05-2018 00:00:00 | localização_00 | 5 | 3 |
O banco de dados do violino pode ser encontrado aqui .
ATUALIZAR:
Graças a @Gerard H. Pille , eu ajusto um pouco a resposta dele a isso:
SELECT
DATE_TRUNC('month', arrive_date) AS grouped_date,
LOWER(arrive_location) AS location,
x.key::int thing_type, sum(x.value::int) total
FROM preprocess_things
JOIN jsonb_each(data) x ON (x.key::int = ANY('{1,2,3}'::int[]))
GROUP BY grouped_date, location, x.key::int
ORDER BY grouped_date, location, x.key::int;
Como existem alguns casos em que eu só preciso de uma seleção do tipo de coisa e nem todos eles para serem calculados, o único problema é adicionar o JOIN e comparar a velocidade da consulta não é tão boa.
veja db<>violino