Json
如何消除嵌套聚合問題中的 for 循環
我有一個解析問題,我正在使用 plpgsql 中的 FOR LOOP 解決,主要是因為我無法弄清楚如何使用子查詢和嵌套聚合來解決它。我的問題是可以消除 for 循環,如果可以,如何消除?我正在使用 PostgreSQL 版本 11.1。
輸入(JSON):
[{"a":"1","b":"2"},{"c":"3","d":"4","e":""}]
預期輸出:
{{a="1",b="2"},{c="3",d="4",e=""}}
我的plpgsql程式碼:
CREATE OR REPLACE FUNCTION parse(_in JSONB) RETURNS TEXT LANGUAGE plpgsql STABLE AS $BODY$ DECLARE _out TEXT; _parts TEXT[]; _row RECORD; BEGIN FOR _row IN ( SELECT q1.value, ROW_NUMBER() OVER () AS index FROM JSONB_ARRAY_ELEMENTS(_in) q1 ) LOOP _parts[_row.index] := STRING_AGG(CONCAT(q2.key, '=', q2.value::TEXT), ',') FROM JSONB_EACH(_row.value) q2; END LOOP; SELECT CONCAT( '{{', COALESCE(STRING_AGG(q, '},{'), ''), '}}' ) INTO _out FROM UNNEST(_parts) q; RETURN _out; END $BODY$;
跑:
my_db=*# select parse('[{"a":"1","b":"2"},{"c":"3","d":"4","e":""}]'); parse ------------------------------------ {{a="1",b="2"},{c="3",d="4",e=""}} (1 row)
更新:響應額外要求的請求:
- 輸入是一個實際的 json(b) 對象,而不是字元串表示。
- 任何鍵或值都不會有雙引號字元(甚至不是轉義字元。)
- 這些值始終為字元串類型,儘管它們可能為空。
- JSON 中可能有很多元素。
對於所示的範例,純字元串操作可以完成這項工作:
WITH tbl(j) AS (SELECT json '[{"a":"1","b":"2"},{"c":"3","d":"4","e":""}]') SELECT '{' || regexp_replace( left(right(j::text, -1), -1) , '"([^"]+)" *:', '\1=', 'g') || '}' FROM tbl;
如果你有更複雜的鍵和值,這裡是你的函式的重寫。改用簡單的 SQL 函式:
CREATE OR REPLACE FUNCTION f_parse(_in jsonb) RETURNS text LANGUAGE sql STABLE AS $func$ SELECT '{{' || string_agg(part, '},{') || '}}' FROM jsonb_array_elements(_in) q1 CROSS JOIN LATERAL ( SELECT string_agg(q2.key || '=' || q2.value::text, ',') AS part FROM jsonb_each(q1.value) q2 ) q2 $func$;
如果您不相信元素的原始順序得到保證,請使用以下安全變體:
CREATE OR REPLACE FUNCTION f_parse_safe(_in jsonb) RETURNS text LANGUAGE sql STABLE AS $func$ SELECT '{{' || string_agg(part, '},{' ORDER BY q1.ordinality) || '}}' FROM jsonb_array_elements(_in) WITH ORDINALITY q1 CROSS JOIN LATERAL ( SELECT string_agg(q2.key || '=' || q2.value::text, ',' ORDER BY q2.ordinality) AS part FROM jsonb_each(q1.value) WITH ORDINALITY q2 ) q2 $func$;
看:
db<>在這裡擺弄