Postgres 9.4 o más reciente
Obviamente inspirado en esta publicación , Postgres 9.4 agregó las funciones que faltan: ¡
Gracias a Laurence Rowe por el parche y a Andrew Dunstan por comprometerse!
Para deshacer la matriz JSON. Luego use array_agg()
o un constructor ARRAY para construir una matriz Postgres a partir de él. O string_agg()
para construir una text
cadena .
Agregue elementos no anidados por fila en una LATERAL
subconsulta correlacionada. Luego se conserva el orden original y no necesitamos ORDER BY
, GROUP BY
ni siquiera una clave única en la consulta externa. Ver:
Reemplace 'json' con 'jsonb' jsonb
en todos los siguientes códigos SQL.
SELECT t.tbl_id, d.list
FROM tbl t
CROSS JOIN LATERAL (
SELECT string_agg(d.elem::text, ', ') AS list
FROM json_array_elements_text(t.data->'tags') AS d(elem)
) d;
Sintaxis corta:
SELECT t.tbl_id, d.list
FROM tbl t, LATERAL (
SELECT string_agg(value::text, ', ') AS list
FROM json_array_elements_text(t.data->'tags') -- col name default: "value"
) d;
Relacionado:
ARRAY constructor en subconsulta correlacionada:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
Relacionado:
Diferencia sutil : los null
elementos se conservan en matrices reales . Esto no es posible en las consultas anteriores que producen una text
cadena, que no puede contener null
valores. La verdadera representación es una matriz.
Envoltorio de funciones
Para uso repetido, para hacer esto aún más simple, encapsule la lógica en una función:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Lo convierten en una función SQL , para que pueda ser inline en las consultas más grandes.
Hágalo IMMUTABLE
(porque lo es) para evitar evaluaciones repetidas en consultas más grandes y permitirlo en expresiones de índice.
Llamada:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> violín aquí
Postgres 9.3 o anterior
Usa la función json_array_elements()
. Pero obtenemos cadenas dobles entre comillas .
Consulta alternativa con agregación en la consulta externa. CROSS JOIN
elimina filas con matrices faltantes o vacías. También puede ser útil para procesar elementos. Necesitamos una clave única para agregar:
SELECT t.tbl_id, string_agg(d.elem::text, ', ') AS list
FROM tbl t
CROSS JOIN LATERAL json_array_elements(t.data->'tags') AS d(elem)
GROUP BY t.tbl_id;
ARRAY constructor, todavía con cadenas citadas:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
Tenga en cuenta que null
se convierte en el valor de texto "nulo", a diferencia de lo anterior. Incorrecto, estrictamente hablando, y potencialmente ambiguo.
Pobre hombre citando con trim()
:
SELECT t.tbl_id, string_agg(trim(d.elem::text, '"'), ', ') AS list
FROM tbl t, json_array_elements(t.data->'tags') d(elem)
GROUP BY 1;
Recupere una sola fila de tbl:
SELECT string_agg(trim(d.elem::text, '"'), ', ') AS list
FROM tbl t, json_array_elements(t.data->'tags') d(elem)
WHERE t.tbl_id = 1;
Las cadenas forman una subconsulta correlacionada:
SELECT tbl_id, (SELECT string_agg(trim(value::text, '"'), ', ')
FROM json_array_elements(t.data->'tags')) AS list
FROM tbl t;
ARRAY constructor:
SELECT tbl_id, ARRAY(SELECT trim(value::text, '"')
FROM json_array_elements(t.data->'tags')) AS txt_arr
FROM tbl t;
Fiddle SQL original (obsoleto) .
db <> violín aquí.
Relacionado:
Notas (desactualizadas desde la página 9.4)
Necesitaríamos un json_array_elements_text(json)
, el gemelo de json_array_elements(json)
para devolver text
valores adecuados de una matriz JSON. Pero eso parece faltar en el arsenal provisto de funciones JSON . O alguna otra función para extraer un text
valor de un JSON
valor escalar . Parece que me estoy perdiendo ese también.
Así que improvisé trim()
, pero eso fallará en casos no triviales ...
json_extract_path_text(your_column, 'tags')
lo que estás buscando?