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 LATERALsubconsulta correlacionada. Luego se conserva el orden original y no necesitamos ORDER BY, GROUP BYni siquiera una clave única en la consulta externa. Ver:
Reemplace 'json' con 'jsonb' jsonben 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 nullelementos se conservan en matrices reales . Esto no es posible en las consultas anteriores que producen una textcadena, que no puede contener nullvalores. 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 JOINelimina 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 nullse 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 textvalores adecuados de una matriz JSON. Pero eso parece faltar en el arsenal provisto de funciones JSON . O alguna otra función para extraer un textvalor de un JSONvalor 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?