将数组的元素组合成不同的数组
Combine elements of array into different array
我需要拆分数组中的文本元素并按索引将元素 (array_agg) 组合到不同的行中
例如,输入是
'{cat$ball$x... , dog$bat$y...}'::text[]
我需要用“$”拆分每个元素,所需的输出是:
{cat,dog} - row 1
{ball,bat} - row 2
{x,y} - row 3
...
抱歉第一次没说清楚。我已经编辑了我的问题。我尝试了类似的选项,但无法弄清楚如何使用以 '$' sysmbol
分隔的多个文本元素来获取它
有点乱,但您可以取消嵌套数组,使用正则表达式分隔文本,然后再次聚合备份:
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 语句中聚合回一个数组。
每个数组元素恰好两部分(原题)
使用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;
相关:
- Split comma separated column data into additional columns
一般解决方案(更新问题)
对于any个数组,any个元素包含any个部分.
演示 table 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;
详情:
- PostgreSQL unnest() with element number
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;
每个查询 returns:
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 值,使其适用于不同数量的部分,但这超出了这个问题的范围:
- PostgreSQL Crosstab Query
我需要拆分数组中的文本元素并按索引将元素 (array_agg) 组合到不同的行中
例如,输入是
'{cat$ball$x... , dog$bat$y...}'::text[]
我需要用“$”拆分每个元素,所需的输出是:
{cat,dog} - row 1
{ball,bat} - row 2
{x,y} - row 3
...
抱歉第一次没说清楚。我已经编辑了我的问题。我尝试了类似的选项,但无法弄清楚如何使用以 '$' sysmbol
分隔的多个文本元素来获取它有点乱,但您可以取消嵌套数组,使用正则表达式分隔文本,然后再次聚合备份:
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 语句中聚合回一个数组。
每个数组元素恰好两部分(原题)
使用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;
相关:
- Split comma separated column data into additional columns
一般解决方案(更新问题)
对于any个数组,any个元素包含any个部分.
演示 table 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;
详情:
- PostgreSQL unnest() with element number
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;
每个查询 returns:
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 值,使其适用于不同数量的部分,但这超出了这个问题的范围:
- PostgreSQL Crosstab Query