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 deORDER 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 deSELECT
lijst,NULLIF
vervangt een overeenkomende naam doorNULL
, wat hetzelfde resultaat oplevert als hierboven.
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:
- Hoe zet je json-array om in postgres-array?
- PostgreSQL unnest() met elementnummer
- Index voor het vinden van een element in een JSON-array
- Tijdsgebaseerde prioriteit in Actieve recordquery
- Selecteer eerst rij in elke GROUP BY-groep?