sql >> Database >  >> RDS >> PostgreSQL

Moet een JSON-array-element dynamisch selecteren uit een postgresql-tabel

json in Postgres 9.3

Dit is moeilijk in pg 9.3, omdat nuttige functionaliteit ontbreekt.

Methode 1

Unnest in een LEFT JOIN LATERAL (schone en standaardconforme), dubbele aanhalingstekens uit json knippen na casten naar text . Zie onderstaande links.

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;

Hoewel dit werkt, en ik heb het nog nooit zien mislukken, hangt de volgorde van niet-geneste elementen af ​​van ongedocumenteerd gedrag. Zie onderstaande links!
Verbeterde conversie van json naar text met de uitdrukking aangeleverd door @pozs in de reactie . Nog steeds hackachtig, maar zou veilig moeten zijn.

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;
  • Unnest in de SELECT lijst (niet-standaard).
  • Voeg rijnummer toe (rn ) parallel (betrouwbaarder).
  • Converteren naar text zoals hierboven.
  • De uitdrukking (last = name) in de ORDER BY clausule sorteert overeenkomende namen als laatste (maar vóór NULL). Een overeenkomende naam wordt dus alleen geselecteerd als er geen andere naam beschikbaar is. Laatste link hieronder.In de SELECT lijst, NULLIF vervangt een overeenkomende naam door NULL , wat hetzelfde resultaat oplevert als hierboven.

SQL Fiddle.

json of jsonb in Postgres 9.4

pg 9.4 levert alle noodzakelijke verbeteringen:

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;

Gebruik jsonb_array_elements_text() voor jsonb . Al het andere hetzelfde.

json / jsonb-functies in de handleiding

Gerelateerde antwoorden met meer uitleg:




  1. Standaard datum/tijd met Ecto &Elixir

  2. PostgreSQL:Hoe kom ik erachter dat er ontbrekende getallen in een kolom zijn met behulp van Genereer_series()?

  3. Klopt het dat het aantal kolommen geen invloed heeft op de prestaties van de database, maar het aantal rijen wel?

  4. Wijzig kolomgegevenstype van Tekst naar Integer in PostgreSQL