PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Sie müssen ein JSON-Array-Element dynamisch aus einer Postgresql-Tabelle auswählen

json in Postgres 9.3

Dies ist in Seite 9.3 schwierig, da nützliche Funktionen fehlen.

Methode 1

Entschachteln Sie in einem LEFT JOIN LATERAL (sauber und standardkonform), doppelte Anführungszeichen von json entfernen nach dem Casting in text . Siehe Links unten.

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;

Obwohl dies funktioniert und ich noch nie gesehen habe, dass es fehlgeschlagen ist, hängt die Reihenfolge der nicht verschachtelten Elemente von undokumentiertem Verhalten ab. Siehe Links unten!
Konvertierung von json verbessert zu text mit dem Ausdruck bereitgestellt von @pozs im Kommentar . Immer noch hackish, sollte aber sicher sein.

Methode 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;
  • Entschachteln Sie im SELECT Liste (kein Standard).
  • Zeilennummer anhängen (rn ) parallel (zuverlässiger).
  • In text umwandeln wie oben.
  • Der Ausdruck (last = name) im Feld ORDER BY -Klausel sortiert übereinstimmende Namen zuletzt (aber vor NULL). Ein passender Name wird also nur ausgewählt, wenn kein anderer Name verfügbar ist. Letzter Link unten. Im SELECT Liste, NULLIF ersetzt einen übereinstimmenden Namen durch NULL , und komme zum selben Ergebnis wie oben.

SQL-Fiddle.

json oder jsonb in Postgres 9.4

pg 9.4 enthält alle notwendigen Verbesserungen:

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;

Verwenden Sie jsonb_array_elements_text() für jsonb . Alles andere gleich.

json / jsonb-Funktionen im Handbuch

Verwandte Antworten mit mehr Erklärung: