In a Postgres 12 database, I have a simple schema containing a JSON column. The JSON will always contain an object, and inside the object there are always 14 keys like so:
CREATE TABLE json_unpacking (foo text, bar json);
INSERT INTO json_unpacking VALUES
(
'ziggy',
'{"Baz (1998-03-12)":1.4285714286,"Baz (1998-03-13)":7.1428571429,"Baz (1998-03-14)":10.8571428571,"Baz (1998-03-15)":11.2857142857,"Baz (1998-03-16)":12.0,"Baz (1998-03-17)":18.1428571429,"Baz (1998-03-18)":2.0,"Baz (1998-03-19)":2.5714285714,"Baz (1998-03-20)":12.2857142857,"Baz (1998-03-21)":3.2857142857,"Baz (1998-03-22)":5.5734285714,"Baz (1998-03-23)":4.1428571429,"Baz (1998-03-24)":11.2857142857,"Baz (1998-03-25)":6.0}'
),
(
'zoggy',
'{"Baz (1998-04-12)":1.7285714286,"Baz (1998-04-13)":6.8578886549,"Baz (1998-04-14)":6.8574428571,"Baz (1998-04-15)":21.2857142857,"Baz (1998-04-16)":7.0,"Baz (1998-04-17)":3.1128571429,"Baz (1998-04-18)":5.0,"Baz (1998-04-19)":7.2214285714,"Baz (1998-04-20)":42.6857142857,"Baz (1998-04-21)":2.9857142857,"Baz (1998-04-22)":5.5734285714,"Baz (1998-04-23)":4.1428571429,"Baz (1998-03-24)":6.7537146517,"Baz (1998-04-25)":47.0}'
)
;
I'm able to query this table just fine, for instance:
SELECT *
FROM json_unpacking
Produces the output that you'd expect:
foo | bar |
---|---|
ziggy | {"Baz (1998-03-12)":1.4285714286,"Baz (1998-03-13)":7.1428571429,"Baz (1998-03-14)":10.8571428571,"Baz (1998-03-15)":11.2857142857,"Baz (1998-03-16)":12.0,"Baz (1998-03-17)":18.1428571429,"Baz (1998-03-18)":2.0,"Baz (1998-03-19)":2.5714285714,"Baz (1998-03-20)":12.2857142857,"Baz (1998-03-21)":3.2857142857,"Baz (1998-03-22)":5.5734285714,"Baz (1998-03-23)":4.1428571429,"Baz (1998-03-24)":11.2857142857,"Baz (1998-03-25)":6.0} |
zoggy | {"Baz (1998-04-12)":1.7285714286,"Baz (1998-04-13)":6.8578886549,"Baz (1998-04-14)":6.8574428571,"Baz (1998-04-15)":21.2857142857,"Baz (1998-04-16)":7.0,"Baz (1998-04-17)":3.1128571429,"Baz (1998-04-18)":5.0,"Baz (1998-04-19)":7.2214285714,"Baz (1998-04-20)":42.6857142857,"Baz (1998-04-21)":2.9857142857,"Baz (1998-04-22)":5.5734285714,"Baz (1998-04-23)":4.1428571429,"Baz (1998-03-24)":6.7537146517,"Baz (1998-04-25)":47.0} |
Now, I'd like to query this table and produce a structure with 15 total columns: "foo"
plus 14 like "bar 1", "bar 2", ... "bar 14"
.
The JSON structure will always include a string pattern (which includes the date), and a numeric value. I do not want the key value, but I need the number values transposed into columns.
In other words, the output structure that I want is like so:
foo | bar 1 | bar 2 | bar 3 | bar 4 | bar 5 | bar 6 | bar 7 | bar 8 | bar 9 | bar 10 | bar 11 | bar 12 | bar 13 | bar 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ziggy | 1.428571429 | 7.142857143 | 10.85714286 | 11.28571429 | 12 | 18.14285714 | 2 | 2.571428571 | 12.28571429 | 3.285714286 | 5.573428571 | 4.142857143 | 11.28571429 | 6 |
zoggy | 1.728571429 | 6.857888655 | 6.857442857 | 21.28571429 | 7 | 3.112857143 | 5 | 7.221428571 | 42.68571429 | 2.985714286 | 5.573428571 | 4.142857143 | 6.753714652 | 47 |
I suppose I have two questions:
- Is this possible?
- Can it be done without any extension?
A colleague has suggested that the crosstab()
function from the tablefunc extension might be required. I've tried various Postgres JSON functions, but have only succeeded in getting either the keys (e.g. using json_object_keys()
) or null values (using json_to_record()
).
Here's a DBfiddle of the problem: https://dbfiddle.uk/?rdbms=postgres_12&fiddle=22e9c99a954eafdadcde657b38f41b3a