2015-04-13 6 views
2

J'ai une table bank_accounts:Comment obtenir des éléments avec un nombre unique à partir d'un tableau json dans PostgreSQL?

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 |    | 

Et il a quelques JSON dans la colonne jsonb:

id | name |        bank_accounts        
----+-------+-------------------------------------------------------------------------- 
    1 | test1 | [{"name": "acct1", "balance": -500}, {"name": "acct2", "balance": -300}] 

Et je suis en utilisant jsonb_array_elements pour obtenir une liste des comptes pour un utilisateur:

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 

Tout est génial. Mais comment puis-je obtenir chaque ligne pour avoir un identifiant unique? Je souhaite mapper chaque ligne à un objet en veille prolongée, mais j'ai du mal à le faire car je n'arrive pas à trouver un moyen d'obtenir un identifiant unique pour chaque ligne.

Répondre

2

Essayer une autre approche propre avec 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; 

Si vous ne se soucient pas des lignes avec des valeurs vides ou nulles dans bank_accounts, utilisez un simple 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); 

La clé L'élément pour votre problème est WITH ORDINALITY qui produit des numéros de ligne à la volée pour les fonctions de retour de jeu. Il a été introduit avec Postgres 9.4 - travaille pour vous, jsonb a également été introduit avec 9.4.

Celles-ci sont uniques par ligne sous-jacente. Pour être unique dans toute la table, ajoutez le id de la table sous-jacente.

Détails pour WITH ORDINALITY:

connexes:

+0

Fantastique! Merci beaucoup. Oui, ça fonctionne parfaitement. J'ai besoin d'enrouler ma tête autour de la jointure latérale et avec l'ordinalité .. – user4782738