PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Besoin de sélectionner dynamiquement un élément de tableau JSON à partir d'une table postgresql

json dans Postgres 9.3

C'est difficile dans la page 9.3, car il manque des fonctionnalités utiles.

Méthode 1

Désimbriquer dans un LEFT JOIN LATERAL (propre et conforme à la norme), supprimez les guillemets doubles de json après la conversion en text . Voir les liens ci-dessous.

SELECT DISTINCT ON (1)
       t.id, t.name, d.last
FROM   tbl t
LEFT   JOIN LATERAL (
  SELECT ('[' || d::text || ']')::json->>0 AS last
  FROM   json_array_elements(t.data) d
  ) d ON d.last <> t.name
ORDER  BY 1, row_number() OVER () DESC;

Bien que cela fonctionne, et je ne l'ai jamais vu échouer, l'ordre des éléments non imbriqués dépend d'un comportement non documenté. Voir les liens ci-dessous !
Amélioration de la conversion depuis json en text avec l'expression fourni par @pozs dans le commentaire . Toujours hackish, mais devrait être sûr.

Méthode 2

SELECT DISTINCT ON (1)
       id, name, NULLIF(last, name) AS last
FROM (
   SELECT t.id, t.name
        ,('[' || json_array_elements(t.data)::text || ']')::json->>0 AS last
        , row_number() OVER () AS rn
   FROM   tbl t
   ) sub
ORDER  BY 1, (last = name), rn DESC;
  • Désimbriquer dans le SELECT liste (non standard).
  • Joindre le numéro de ligne (rn ) en parallèle (plus fiable).
  • Convertir en text comme ci-dessus.
  • L'expression (last = name) dans le ORDER BY La clause trie les noms correspondants en dernier (mais avant NULL). Ainsi, un nom correspondant n'est sélectionné que si aucun autre nom n'est disponible. Dernier lien ci-dessous.Dans le SELECT liste, NULLIF remplace un nom correspondant par NULL , en arrivant au même résultat que ci-dessus.

SQL Fiddle.

json ou jsonb dans Postgres 9.4

pg 9.4 embarque toutes les améliorations nécessaires :

SELECT DISTINCT ON (1)
       t.id, t.name, d.last
FROM   tbl t
LEFT   JOIN LATERAL json_array_elements_text(data) WITH ORDINALITY d(last, rn)
       ON d.last <> t.name
ORDER  BY d.rn DESC;

Utilisez jsonb_array_elements_text() pour jsonb . Tout le reste pareil.

fonctions json / jsonb dans le manuel

Réponses associées avec plus d'explications :