Postgres 9.4 ou mais recente
Obviamente inspirado neste post , o Postgres 9.4 adicionou as funções ausentes:
Obrigado a Laurence Rowe pelo patch e Andrew Dunstan por cometer!
Desnaturar a matriz JSON. Em seguida, use array_agg()
ou um construtor ARRAY para criar uma matriz do Postgres a partir dele. Ou string_agg()
para construir uma text
string .
Agregue elementos não aninhados por linha em uma LATERAL
subconsulta ou correlacionada. O pedido original é preservado e não precisamos ORDER BY
, GROUP BY
nem mesmo uma chave exclusiva na consulta externa. Vejo:
Substitua 'json' por 'jsonb' jsonb
em todos os seguintes 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;
Sintaxe curta:
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:
Construtor ARRAY na subconsulta correlacionada:
SELECT tbl_id, ARRAY(SELECT json_array_elements_text(t.data->'tags')) AS txt_arr
FROM tbl t;
Relacionado:
Diferença sutil : os null
elementos são preservados em matrizes reais . Isso não é possível nas consultas acima produzindo uma text
sequência que não pode conter null
valores. A representação verdadeira é uma matriz.
Wrapper de função
Para uso repetido, para tornar isso ainda mais simples, encapsule a lógica em uma função:
CREATE OR REPLACE FUNCTION json_arr2text_arr(_js json)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT json_array_elements_text(_js))';
Torne-a uma função SQL , para que possa ser incorporada em consultas maiores.
Faça isso IMMUTABLE
(porque é) para evitar a avaliação repetida em consultas maiores e permita-o em expressões de índice.
Ligar:
SELECT tbl_id, json_arr2text_arr(data->'tags')
FROM tbl;
db <> mexer aqui
Postgres 9.3 ou anterior
Use a função json_array_elements()
. Mas obtemos strings com aspas duplas .
Consulta alternativa com agregação na consulta externa. CROSS JOIN
remove linhas com matrizes ausentes ou vazias. Também pode ser útil para processar elementos. Precisamos de uma chave exclusiva 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;
Construtor ARRAY, ainda com seqüências de caracteres citadas:
SELECT tbl_id, ARRAY(SELECT json_array_elements(t.data->'tags')) AS quoted_txt_arr
FROM tbl t;
Observe que null
é convertido para o valor do texto "nulo", diferente da acima. Incorreto, estritamente falando, e potencialmente ambíguo.
O pobre homem não cita 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 uma única linha 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;
Strings formam subconsulta correlacionada:
SELECT tbl_id, (SELECT string_agg(trim(value::text, '"'), ', ')
FROM json_array_elements(t.data->'tags')) AS list
FROM tbl t;
Construtor ARRAY:
SELECT tbl_id, ARRAY(SELECT trim(value::text, '"')
FROM json_array_elements(t.data->'tags')) AS txt_arr
FROM tbl t;
SQL Fiddle original (desatualizado) .
db <> mexa aqui.
Relacionado:
Notas (desatualizadas desde a página 9.4)
Nós precisaríamos de um json_array_elements_text(json)
, o gêmeo de, json_array_elements(json)
para retornar text
valores adequados de uma matriz JSON. Mas isso parece estar faltando no arsenal fornecido de funções JSON . Ou alguma outra função para extrair um text
valor de um JSON
valor escalar . Parece que sinto falta também.
Então eu improvisei com trim()
, mas isso falhará em casos não triviais ...
json_extract_path_text(your_column, 'tags')
que você está procurando?