如何从 PostgreSQL 的 json 数组中获取具有唯一编号的元素?

use*_*738 5 arrays postgresql json set-returning-functions jsonb

我有一张桌子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 |              | 
Run Code Online (Sandbox Code Playgroud)

它在jsonb列中有一些 JSON :

 id | name  |                              bank_accounts                               
----+-------+--------------------------------------------------------------------------
  1 | test1 | [{"name": "acct1", "balance": -500}, {"name": "acct2", "balance": -300}]
Run Code Online (Sandbox Code Playgroud)

我正在使用 jsonb_array_elements 获取一个用户的帐户列表:

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
Run Code Online (Sandbox Code Playgroud)

这一切都很棒。但是如何让每一行都有一个唯一的 id?我想将每一行映射到一个休眠对象,但我在这样做时遇到了麻烦,因为我找不到让每一行都具有唯一 ID 的方法。

Erw*_*ter 7

尝试不同的、干净的方法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;
Run Code Online (Sandbox Code Playgroud)

如果您不关心 中具有空值或空值的行bank_accounts,请使用更简单的CROSS JOIN

select b.id, t.rn
     , t.account->>'name' AS name
     , t.account->>'balance' AS balance
FROM   bank_accounts b
     , jsonb_array_elements(b.bank_accounts) WITH ORDINALITY AS t (account, rn);
Run Code Online (Sandbox Code Playgroud)

您的问题的关键要素是WITH ORDINALITY为集合返回函数动态生成行号。它是在 Postgres 9.4 中引入的 - 对你有用,jsonb也在 9.4 中引入。

这些对于每个底层行都是唯一的。要在整个表中唯一,请添加id基础表的 。

详情WITH ORDINALITY

有关的: