我正在使用PostgreSQL 9.4,我正在尝试在数组中传输列值。对于“普通”(非用户定义)数据类型,我可以使用它。
为了详细解释我的问题,我编写了一个最小的例子。 假设我们定义一个复合类型“compo”并创建一个表“test_rel”并插入一些值。看起来像这样,对我有用:
CREATE TYPE compo AS(a int, b int);
CREATE TABLE test_rel(t1 compo[],t2 int);
INSERT INTO test_rel VALUES('{"(1,2)"}',3);
INSERT INTO test_rel VALUES('{"(4,5)","(6,7)"}',3);
接下来,我们尝试获取包含列t2值的数组。以下也有效:
SELECT array(SELECT t2 FROM test_rel WHERE t2='3');
现在,我们尝试使用列t1(具有复合类型的列)执行相同的操作。我现在的问题是,以下情况不起作用:
SELECT array(SELECT t1 FROM test_rel WHERE t2='3');
ERROR: could not find array type for data type compo[]
有人可以给我一个提示,为什么同样的陈述不适用于复合类型?我不仅是stackoverflow的新手,也是PostgreSQL和plpgsql的新手。所以,请告诉我,当我做错事的时候。
答案 0 :(得分:5)
在PostgreSQL mailing list中对此进行了一些讨论。
长话短说,两者都
select array(select array_type from ...)
select array_agg(array_type) from ...
表示数组数组的概念,PostgreSQL不支持。 PostgreSQL支持多维数组,但它们必须是矩形的。 F.ex. ARRAY[[0,1],[2,3]]
有效,但ARRAY[[0],[1,2]]
不是。
array constructor& 9.5中的array_agg()
function。
现在,他们明确指出,他们会将数组参数作为多维数组累积,但前提是它的所有部分都具有相同的维度。
array()
构造函数:如果子查询的输出列是数组类型,则结果将是一个相同类型但一个更高维度的数组;在这种情况下,所有子查询行必须生成具有相同维度的数组,否则结果将不是矩形。
array_agg(any array type)
:输入数组连接成一个更高维度的数组(输入必须都具有相同的维度,不能为空或NULL
)
对于9.4,你可以将数组包装成row
:这样你就可以创建一些几乎 数组数组:< / p>
SELECT array(SELECT ROW(t1) FROM test_rel WHERE t2='3');
SELECT array_agg(ROW(t1)) FROM test_rel WHERE t2='3';
或者,您可以使用recursive CTE(和数组连接)来解决问题,例如:
with recursive inp(arr) as (
values (array[0,1]), (array[1,2]), (array[2,3])
),
idx(arr, idx) as (
select arr, row_number() over ()
from inp
),
agg(arr, idx) as (
select array[[0, 0]] || arr, idx
from idx
where idx = 1
union all
select agg.arr || idx.arr, idx.idx
from agg
join idx on idx.idx = agg.idx + 1
)
select arr[array_lower(arr, 1) + 1 : array_upper(arr, 1)]
from agg
order by idx desc
limit 1;
但当然这个解决方案高度依赖于您的数据(维度)。