【问题标题】:Combine elements of array into different array将数组的元素组合成不同的数组
【发布时间】:2016-09-25 04:05:10
【问题描述】:

我需要拆分数组中的文本元素,并通过索引将元素(array_agg)组合到不同的行中

例如,输入是

'{cat$ball$x... , dog$bat$y...}'::text[]

我需要用'$'分割每个元素,所需的输出是:

{cat,dog} - row 1
{ball,bat} - row 2
{x,y} - row 3
...

很抱歉第一次没有说清楚。我已经编辑了我的问题。我尝试了类似的选项,但无法弄清楚如何使用以 '$' sysmbol 分隔的多个文本元素来获取它

【问题讨论】:

  • 列表是什么意思?到目前为止,您尝试了什么?

标签: sql arrays postgresql unnest


【解决方案1】:

有点乱,但您可以取消嵌套数组,使用正则表达式分隔文本,然后再次聚合:

with a as (select unnest('{cat$ball, dog$bat}'::_text) some_text),
b as (select regexp_matches(a.some_text, '(^[a-z]*)\$([a-z]*$)') animal_object from a)
select array_agg(animal_object[1]) animal, array_agg(animal_object[2]) a_object
from b

如果您一次处理多条记录,您可能希望在 unnest 之前使用行号之类的东西,以便在最终的 select 语句中使用 group by 聚合回数组。

【讨论】:

    【解决方案2】:

    每个数组元素正好两部分(原始问题)

    使用unnest()split_part()array_agg()

    SELECT array_agg(split_part(t, '$', 1)) AS col1
         , array_agg(split_part(t, '$', 2)) AS col2
    FROM   unnest('{cat$ball, dog$bat}'::text[]) t;
    

    相关:

    一般解决方案(更新问题)

    对于任意个数组,其中任意个元素包含任意个部分。

    表格演示tbl

    CREATE TABLE tbl (tbl_id int PRIMARY KEY, arr text[]);
    
    INSERT INTO tbl VALUES
      (1, '{cat1$ball1, dog2$bat2}')  -- 2 parts per array element, 2 elements
    , (2, '{cat$ball$x, dog$bat$y}')  -- 3 parts ...
    , (3, '{a1$b1$c1$d1, a2$b2$c2$d2, a3$b3$c3$d3}');  -- 4 parts, 3 elements
    

    查询:

    SELECT tbl_id, idx, array_agg(elem ORDER BY ord) AS pivoted_array
    FROM   tbl t
         , unnest(t.arr) WITH ORDINALITY a1(string, ord)
         , unnest(string_to_array(a1.string, '$')) WITH ORDINALITY a2(elem, idx)
    GROUP  BY tbl_id, idx
    ORDER  BY tbl_id, idx;
    

    我们在这里查看两个(嵌套的)LATERAL 连接。 LATERAL 需要 Postgres 9.3。详情:

    WITH ORDINALITY 第一个unnest() 有待讨论。一个更简单的查询通常也可以工作。只是不能保证按照 SQL 标准工作:

    SELECT tbl_id, idx, array_agg(elem) AS pivoted_array
    FROM   tbl t
         , unnest(t.arr) string
         , unnest(string_to_array(string, '$')) WITH ORDINALITY a2(elem, idx)
    GROUP  BY tbl_id, idx
    ORDER  BY tbl_id, idx;
    

    详情:

    WITH ORDINALITY 需要 Postgres 9.4 或更高版本。对 Postgres 9.3 进行了相同的回补:

    SELECT tbl_id, idx, array_agg(arr2[idx]) AS pivoted_array
    FROM   tbl t
         , LATERAL (
             SELECT string_to_array(string, '$') AS arr2  -- convert string to array
             FROM   unnest(t.arr) string  -- unnest org. array
             ) x
         , generate_subscripts(arr2, 1) AS idx  -- unnest 2nd array with ord. numbers
    GROUP  BY tbl_id, idx
    ORDER  BY tbl_id, idx;
    

    每个查询返回:

     tbl_id | idx | pivoted_array
    --------+-----+---------------
          1 |   1 | {cat,dog}
          1 |   2 | {bat,ball}
          1 |   3 | {y,x}
          2 |   1 | {cat2,dog2}
          2 |   2 | {ball2,bat2}
          3 |   1 | {a3,a1,a2}
          3 |   2 | {b1,b2,b3}
          3 |   3 | {c2,c1,c3}
          3 |   4 | {d2,d3,d1}
    

    SQL Fiddle(仍然停留在第 9.3 页)。

    这些查询的唯一要求是同一数组的元素中的部分数是恒定的。我们甚至可以使用带有两个参数的 crosstab() 使其适用于不同数量的部件,以填充缺失部件的 NULL 值,但这超出了本问题的范围:

    【讨论】:

    • 感谢您的回复!!。很抱歉第一次没有说清楚。我尝试了类似的事情,现在尝试解决用“$”符号分隔的不同数量的字符串。此外,每个数组元素中以“$”分隔的文本数量将始终相同
    • 谢谢!! (对于解决方案和参考)。好好学习!!
    猜你喜欢
    • 2019-12-25
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 2021-10-30
    • 2019-12-05
    • 1970-01-01
    • 2011-08-08
    相关资源
    最近更新 更多