PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Precisa selecionar um elemento de matriz JSON dinamicamente de uma tabela postgresql

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) no ORDER 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. No SELECT lista, NULLIF substitui um nome correspondente por NULL , 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: