json
no Postgres 9.3
Isso é difícil na página 9.3, porque faltam funcionalidades úteis.
Método 1
Desaninhar em um
LEFT JOIN LATERAL
(limpo e em conformidade com o padrão), corte aspas duplas de json
após a conversão para text
. Veja os links abaixo. 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;
Embora isso funcione, e eu nunca o vi falhar, a ordem dos elementos não aninhados depende do comportamento não documentado. Veja os links abaixo!
Melhorou a conversão de
json
para text
com a expressão fornecido por @pozs no comentário
. Ainda hackish, mas deve ser seguro. Método 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;
- Desaninhar no
SELECT
lista (não padrão). - Anexar o número da linha (
rn
) em paralelo (mais confiável). - Converter em
text
como acima. - A expressão
(last = name)
noORDER BY
cláusula classifica os nomes correspondentes por último (mas antes de NULL). Portanto, um nome correspondente só é selecionado se nenhum outro nome estiver disponível. Último link abaixo. NoSELECT
lista,NULLIF
substitui um nome correspondente porNULL
, chegando ao mesmo resultado acima.
SQL Fiddle.
json
ou jsonb
no Postgres 9.4
pg 9.4 envia todas as melhorias necessárias:
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;
Use
jsonb_array_elements_text()
para jsonb
. Todo o resto igual. funções json / jsonb no manual
Respostas relacionadas com mais explicações:
- Como transformar array json em array postgres?
- PostgreSQL unnest() com número de elemento
- Índice para encontrar um elemento em uma matriz JSON
- Prioridade baseada em tempo em Consulta de registro ativo
- Selecione primeiro linha em cada grupo GROUP BY?