如何从多个值中反对 row_to_json 和 array_agg

问题描述

我设法创建了一个 jsonb 输出,但是我需要将它作为对象

我当前的代码

create function extract_data()
  returns jsonb
as
$$
declare
  v_msgar text[];
  v_result jsonb;
  analyzer_test_full_desc character varying;
  data_reading character varying;
begin
  v_msgar := array['P|61||||^^||^^|U||||||||||||||||||||||||||<CR>','O|61|15^1^15|KK4002259|glu^glucose (GOD-POD Method)^^','R|170|AST^Aspartate Aminotransferase^^F|22.657989^^^^','R|171|ALP^Alkaline phosphatase^^F|107.636995^^^^','R|172|TP^Total Protein^^F|85.245151^^^^','R|173|TG^Triglycerides^^F|1.348633^^^^','R|174|HDL^HDL-Cholesterol^^F|1.238458^^^^','R|175|CHOL^Total Cholesterol^^F|5.073630^^^^','R|176|UA^Uric Acid^^F|309.705876^^^^','R|177|BUN^Urea^^F|4.412234^^^^'];

           SELECT split_part(items[3],'^',1)
                  INTO  analyzer_test_full_desc
                FROM (
                  SELECT string_to_array(element,'|') as items
                 FROM unnest(v_msgar) as t(element)) t   
            WHERE items[1] = 'R';
        
            SELECT  split_part(items[4],1)
                  INTO data_reading
                FROM (
                  SELECT string_to_array(element,'|') as items
                 FROM unnest(v_msgar) as t(element)) t   
            WHERE items[1] = 'R';

            SELECT array_to_json(array_agg(row_to_json(t))) 
                 FROM (
                SELECT analyzer_test_full_desc as resultId,data_reading as resultValue
            ) t INTO v_result;
  
  return v_result;
end;  
$$
language plpgsql;  

输出

[{"resultid": "AST","resultvalue": "22.657989"}]

我希望输出是这样的

[{"resultid": "AST","resultvalue": "22.657989"},{"resultid": "ALP","resultvalue": "107.636995"},{"resultid": "TP","resultvalue": "85.245151"]

我尝试循环选择语句,但仍然没有解决方案。

解决方法

step-by-step demo:db<>fiddle

您不一定需要存储过程,一个简单的查询就足够了:

SELECT
    jsonb_agg(                                      -- 6
        jsonb_build_object(                         -- 5
            'resultid',split_part(parts[3],'^',1),-- 4
            'resultvalue',split_part(parts[4],1)
        )
    )
FROM mytable t,unnest(myarray) as elem,-- 1
    regexp_split_to_array(elem,'\|') as parts      -- 2
WHERE parts[1] = 'R'                                -- 3
  1. 将所有数组元素展开成一个记录
  2. 在分隔符 | 上将元素拆分为一个新数组
  3. 过滤所有 R 元素
  4. 获取预期的部分并检索 ^ 字符之前的值
  5. 构建预期的 JSON 元素
  6. 将它们聚合成一个 JSON 数组

不过,如果你需要一个存储过程,当然可以把这个查询包装成一个:

create function extract_data()
  returns jsonb
as
$$
declare
  v_result jsonb;
begin

    SELECT
        ...
    INTO v_result
    FROM ...

    RETURN v_result;

end;  
$$
language plpgsql;

最后,您也可以将数组作为函数输入参数,而不是采用表输入:

create function extract_data(myarray text[])
  returns jsonb
as
$$
declare
  v_result jsonb;
begin

    SELECT
        jsonb_agg(
            jsonb_build_object(
                'resultid','resultvalue',1)
            )
        )
    INTO v_result
    FROM unnest(myarray) as elem,regexp_split_to_array(elem,'\|') as parts
    WHERE parts[1] = 'R';

    RETURN v_result;

end;  
$$
language plpgsql;
,

您不需要 pl/pgsql 来执行此操作。在一个(内部)查询中提取您需要的数据部分,然后像这样聚合它们:

create or replace function extract_data(text[]) returns jsonb as
$$
select jsonb_agg(to_jsonb(t.*)) from 
(
 select split_part(split_part(arr,'|',3),1) as "resultId",split_part(split_part(arr,4),1) as "resultValue"
 from unnest($1) arr
 where split_part(arr,1) = 'R'
) t;
$$ language sql;

select extract_data(array[
 'P|61||||^^||^^|U||||||||||||||||||||||||||<CR>','O|61|15^1^15|KK4002259|GLU^Glucose (GOD-POD Method)^^','R|170|AST^Aspartate Aminotransferase^^F|22.657989^^^^','R|171|ALP^Alkaline phosphatase^^F|107.636995^^^^','R|172|TP^Total Protein^^F|85.245151^^^^','R|173|TG^Triglycerides^^F|1.348633^^^^','R|174|HDL^HDL-Cholesterol^^F|1.238458^^^^','R|175|CHOL^Total Cholesterol^^F|5.073630^^^^','R|176|UA^Uric Acid^^F|309.705876^^^^','R|177|BUN^Urea^^F|4.412234^^^^'
]);

为了使函数可重用,将数据数组作为参数传递,而不是将其硬编码在函数体内。