sql >> Base de Datos >  >> RDS >> PostgreSQL

Necesita seleccionar un elemento de matriz JSON dinámicamente desde una tabla postgresql

json en Postgres 9.3

Esto es difícil en la página 9.3, porque falta una funcionalidad útil.

Método 1

Desanidar en un LEFT JOIN LATERAL (limpio y conforme a los estándares), recorte las comillas dobles de json después de enviar a text . Ver enlaces a continuación.

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;

Si bien esto funciona, y nunca lo he visto fallar, el orden de los elementos no anidados depende del comportamiento no documentado. ¡Vea los enlaces a continuación!
Mejoró la conversión de json a text con la expresión proporcionado por @pozs en el comentario . Sigue siendo hackish, pero debería 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;
  • Anular el anidamiento en SELECT lista (no estándar).
  • Adjuntar número de fila (rn ) en paralelo (más fiable).
  • Convertir a text como arriba.
  • La expresión (last = name) en el ORDER BY la cláusula ordena los nombres coincidentes en último lugar (pero antes de NULL). Por lo tanto, solo se selecciona un nombre coincidente si no hay otro nombre disponible. Último enlace a continuación. En SELECT lista, NULLIF reemplaza un nombre coincidente con NULL , llegando al mismo resultado que el anterior.

SQL Fiddle.

json o jsonb en Postgres 9.4

pg 9.4 incluye todas las mejoras necesarias:

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() para jsonb . Todo lo demás igual.

funciones json/jsonb en el manual

Respuestas relacionadas con más explicaciones: