Return jsonb_array_elements 结果为逗号分隔列表

Return jsonb_array_elements result as comma-separated list

我正在访问 jsonb 字段中的数组(一个名为 'choice_values' 的 json 对象),并想将其内容解析为逗号分隔的文本字段。

SELECT
    jsonb_array_elements(doc -> 'form_values' -> '8189' -> 'choice_values')
FROM
    field_data.exports;

那个 jsonb_array_elements 函数 returns a "setof text",我想将其转换为逗号分隔的数组值列表,包含在单个字段中。

谢谢。

string_agg aggregate function 与来自 jsonb_array_elements_text 的子 select 一起使用似乎可行(在 PG 9.5 上测试)。请注意在 PostgreSQL 9.4 中添加的 jsonb_array_elements_text 的使用,而不是 PostgreSQL 9.3 中添加的 jsonb_array_elements

with exports as (
    select $${"form_values": {"8189": {"choice_values": ["a","b","c"]}}}$$::jsonb as doc
)
SELECT
    string_agg(values, ', ')
FROM
    exports, jsonb_array_elements_text(doc -> 'form_values' -> '8189' -> 'choice_values') values
GROUP BY
    exports.doc;

输出:

'a, b, c'

另见 this question and its answers

集合返回函数(如jsonb_array_elements_text())可以在SELECT列表中调用,但它们不能在聚合函数中使用。

这是在 FROM 子句中调用集合返回函数的好习惯,通常在横向连接中,如本例所示:

with the_data as (
    select '["alfa", "beta", "gamma"]'::jsonb as js
    )

select string_agg(elem, ',')
from 
    the_data, 
    jsonb_array_elements_text(js) elem;

   string_agg    
-----------------
 alfa,beta,gamma
(1 row)     

因此您的查询应如下所示:

select string_agg(elem, ',')
from 
    field_data.exports, 
    jsonb_array_elements_text(doc -> 'form_values' -> '8189' -> 'choice_values') elem;

可能不是最佳做法:将 json 数组转换为文本,然后删除括号。

WITH input AS (
    SELECT '["text1","text2","text3"]'::jsonb as data
) 
SELECT substring(data::text,2,length(data::text)-2) FROM input

它的优点是它转换 "in-place",而不是通过聚合。如果您只能访问部分查询,这可能很方便,例如对于某些具有基于字段的转换规则的同步工具,或类似以下内容:

CREATE TEMP TABLE example AS (SELECT '["text1","text2","text3"]'::jsonb as data);
ALTER TABLE example ALTER COLUMN data TYPE text USING substring(data::text,2,length(data::text)-2);