json
i Postgres 9.3
Dette er svært i s. 9.3, fordi brugbar funktionalitet mangler.
Metode 1
Fjern i en LEFT JOIN LATERAL
(ren og standardoverensstemmende), trim dobbelte anførselstegn fra json
efter casting til text
. Se links nedenfor.
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;
Selvom dette virker, og jeg aldrig har set det fejle, afhænger rækkefølgen af uindlejrede elementer af udokumenteret adfærd. Se links nedenfor!
Forbedrede konverteringen fra json
til text
med udtrykket leveret af @pozs i kommentaren
. Stadig hackish, men burde være sikkert.
Metode 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 i
SELECT
liste (ikke-standard). - Vedhæft rækkenummer (
rn
) parallelt (mere pålideligt). - Konverter til
text
som ovenfor. - Udtrykket
(last = name)
iORDER BY
klausul sorterer matchende navne efter (men før NULL). Så et matchende navn vælges kun, hvis der ikke er et andet navn tilgængeligt. Sidste link nedenfor. ISELECT
liste,NULLIF
erstatter et matchende navn medNULL
, hvilket kommer til samme resultat som ovenfor.
json
eller jsonb
i Postgres 9.4
s. 9.4 sender alle de nødvendige forbedringer:
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;
Brug jsonb_array_elements_text()
for jsonb
. Alt andet lige.
json / jsonb-funktioner i manualen
Relaterede svar med mere forklaring:
- Hvordan forvandler jeg json-array til postgres-array?
- PostgreSQL unnest() med elementnummer
- Indeks til at finde et element i et JSON-array
- Tidsbaseret prioritet i Aktiv registreringsforespørgsel
- Vælg først række i hver GRUPPE FOR gruppe?