I have a table bank_accounts
:
Column | Type | Modifiers | Storage | Stats target | Description
---------------+-----------------------+-------------------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('bank_accounts_id_seq'::regclass) | plain | |
name | character varying(50) | | extended | |
bank_accounts | jsonb | not null | extended | |
And it has some JSON in the jsonb
column:
id | name | bank_accounts
----+-------+--------------------------------------------------------------------------
1 | test1 | [{"name": "acct1", "balance": -500}, {"name": "acct2", "balance": -300}]
And I am using jsonb_array_elements to get a list of the accounts for one user:
select jsonb_array_elements(bank_accounts)->>'name' as name, jsonb_array_elements(bank_accounts)->>'balance' as balance from bank_accounts;
name | balance
-------+---------
acct1 | -500
acct2 | -300
That's all great. But how do I get each row to have a unique id? I'd like to map each row to a hibernate object, but I'm having trouble doing that because I can't find a way to get each row to have a unique id.
Querying the JSON documentPostgreSQL has two native operators -> and ->> to query JSON documents. The first operator -> returns a JSON object, while the operator ->> returns text. These operators work on both JSON as well as JSONB columns. There are additional operators available for JSONB columns.
2) Querying PostgreSQL JSON Data To query data, you can use a SELECT statement like in any other SQL query. You can use the native PostgreSQL operators to query the data in PostgreSQL. The operator -> returns a JSON object field by key. The operator ->> returns a JSON object field by text.
PostgreSQL provides two native operators -> and ->> to help you query JSON data. The operator -> returns JSON object field as JSON. The operator ->> returns JSON object field as text.
Try a different, clean approach with JOIN LATERAL
:
SELECT b.id, t.rn
, t.account->>'name' AS name
, t.account->>'balance' AS balance
FROM bank_accounts b
LEFT JOIN LATERAL jsonb_array_elements(b.bank_accounts)
WITH ORDINALITY AS t (account, rn) ON true;
If you don't care for rows with empty or null values in bank_accounts
, use a simpler CROSS JOIN
:
SELECT ...
FROM bank_accounts b
, jsonb_array_elements(b.bank_accounts) WITH ORDINALITY AS t (account, rn);
The key ingredient is WITH ORDINALITY
to produce row numbers for set-returning functions on the fly. It was introduced with Postgres 9.4 - just like jsonb
.
rn
is unique per underlying row in bank_accounts
.
To be unique across the whole result set, combine it with b.id
.
About WITH ORDINALITY
:
Related:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With