So I've got a postgres database in which I've got a jsonb field called details:
sensor | details
------------------
A | [{"direction":"up", "result": 1.0}, {"direction":"up", "result": 2.0}]
B | [{"direction":"up", "result": 3.0}, {"direction":"down", "result": 4.0}]
B | [{"direction":"up", "result": 5.0}, {"direction":"up", "result": 6.0}, {"direction":"down", "result": 7.0}]
A | [{"direction":"down", "result": 8.0}, {"direction":"left", "result": 9.0}]
I now need a sum of the result of all the up records and down records grouped by sensor.
So my query should result in this:
sensor | up_sum | down_sum
---------------------------
A | 3.0 | 8.0
B | 14.0 | 11.0
I need to somehow:
- loop over the details array objects
- filter by
upanddown - and then sum the results for those records per sensor
I guess subqueries are the only way to do this (correct?). I found the postgres documentation on how to handle json, so I started to loop over the objects:
SELECT jsonb_array_elements(details)
FROM table;
That simply gives me a list of the objects. So I now need to filter by up for which I think I need to use json_to_recordset(). I tried this:
SELECT *
FROM json_to_recordset('[{"direction":"up", "result": 1.0}, {"direction":"up", "result": 2.0}, {"direction":"down", "result": 3.0}]') as x(direction varchar, result float)
WHERE direction = 'up';
which results in the expected
direction | result
------------------
up | 1
up | 2
Now let's sum them:
SELECT SUM(result) as up_sum
FROM json_to_recordset('[{"direction":"up", "result": 1.0}, {"direction":"up", "result": 2.0}, {"direction":"down", "result": 3.0}]') as x(direction varchar, result float)
WHERE direction = 'up';
Great, that works!
Now I inserted that into my previous query:
SELECT
jsonb_array_elements(details),
(
SELECT SUM(result)
FROM json_to_recordset('[{"direction":"up", "result": 1.0}, {"direction":"up", "result": 2.0}, {"direction":"down", "result": 3.0}]') as x(direction varchar, result float)
WHERE direction = 'up'
) as up_sum
FROM table;
Ok, that also works great.
Now I just need to use the result of jsonb_array_elements(details) in the json_to_recordset() (or actualy jsonb_to_recordset() for the jsonb field). So I then ran this:
SELECT
jsonb_array_elements(details),
(
SELECT SUM(result)
FROM jsonb_to_recordset(jsonb_array_elements(details)) as x(direction varchar, result float)
WHERE direction = 'up'
) as up_sum
FROM table;
Unfortunately that gives an error:
ERROR: set-returning functions must appear at top level of FROM
Could anybody hint me in the right direction?