web-dev-qa-db-fra.com

Extraire la clé, la valeur des objets json dans Postgres

J'ai une table Postgres dont le contenu est similaire à celui-ci:

id  | data

1   | {"a":"4", "b":"5"}
2   | {"a":"6", "b":"7"}
3   | {"a":"8", "b":"9"}

La première colonne est un entier et la seconde est une colonne json.

Je veux pouvoir développer les clés et les valeurs du json pour que le résultat ressemble à ceci:

id  | key  | value

1   | a    | 4
1   | b    | 5
2   | a    | 6
2   | b    | 7
3   | a    | 8
3   | b    | 9

Cela peut-il être réalisé dans Postgres SQL?


Ce que j'ai essayé

Étant donné que le tableau d'origine peut être simulé en tant que tel:

select *
from 
(
values
(1, '{"a":"4", "b":"5"}'::json),
(2, '{"a":"6", "b":"7"}'::json),
(3, '{"a":"8", "b":"9"}'::json)
) as q (id, data)

Je peux obtenir uniquement les clés en utilisant:

select id, json_object_keys(data::json)
from 
(
values
(1, '{"a":"4", "b":"5"}'::json),
(2, '{"a":"6", "b":"7"}'::json),
(3, '{"a":"8", "b":"9"}'::json)
) as q (id, data)

Et je peux les obtenir sous forme de records comme celui-ci:

select id, json_each(data::json)
from 
(
values
(1, '{"a":"4", "b":"5"}'::json),
(2, '{"a":"6", "b":"7"}'::json),
(3, '{"a":"8", "b":"9"}'::json)
) as q (id, data)

Mais je ne peux pas trouver comment atteindre le résultat avec l'identifiant, la clé et la valeur.

Des idées?

Remarque: le vrai json avec lequel je travaille est beaucoup plus imbriqué que cela, mais je pense que cet exemple représente bien mon problème sous-jacent.

13
Tom G
SELECT q.id, d.key, d.value
FROM q
JOIN json_each_text(q.data) d ON true
ORDER BY 1, 2;

La fonction json_each_text() est une fonction renvoyant un ensemble, vous devez donc l'utiliser comme source de ligne. La sortie de la fonction est ici jointe latéralement à la table q, ce qui signifie que pour chaque ligne de la table, chaque paire (key, value) De la data est jointe uniquement à cette ligne, de sorte que la relation entre la ligne d'origine et les lignes formées à partir de l'objet json est conservée.

La table q peut également être une sous-requête très compliquée (ou une clause VALUES, comme dans votre question). Dans la fonction, la colonne appropriée est utilisée à partir du résultat de l'évaluation de cette sous-requête, vous n'utilisez donc qu'une référence à l'alias de la sous-requête et à la colonne (alias de) de la sous-requête.

19
Patrick