json in Postgres 9.3
Questo è difficile a pag 9.3, perché mancano funzionalità utili.
Metodo 1
Annulla l'annidamento in un LEFT JOIN LATERAL (pulito e conforme agli standard), ritaglia le virgolette doppie da json dopo aver trasmesso a text . Vedi i link sotto.
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;
Sebbene funzioni, e non l'ho mai visto fallire, l'ordine degli elementi non annidati dipende da comportamenti non documentati. Vedi i link sotto!
Migliorata la conversione da json a text con l'espressione fornito da @pozs nel commento
. Ancora hacker, ma dovrebbe essere sicuro.
Metodo 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;
- Disannida in
SELECTelenco (non standard). - Allega il numero di riga (
rn) in parallelo (più affidabile). - Converti in
textcome sopra. - L'espressione
(last = name)nelORDER BYla clausola ordina i nomi corrispondenti per ultimi (ma prima di NULL). Quindi un nome corrispondente viene selezionato solo se non sono disponibili altri nomi. Ultimo link sotto.NelSELECTelenco,NULLIFsostituisce un nome corrispondente conNULL, arrivando allo stesso risultato di cui sopra.
json o jsonb in Postgres 9.4
pg 9.4 fornisce tutti i miglioramenti necessari:
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;
Usa jsonb_array_elements_text() per jsonb . Tutto il resto uguale.
funzioni json / jsonb nel manuale
Risposte correlate con più spiegazioni:
- Come trasformare l'array json in un array postgres?
- PostgreSQL unnest() con numero elemento
- Indice per trovare un elemento in un array JSON
- Priorità basata sul tempo in Interrogazione record attiva
- Seleziona prima riga in ogni gruppo GROUP BY?