我曾期望unnest()
返回数组的索引1到array_length()
的一行,但显然不是这样。请考虑以下示例:
create table T (
id int,
list int[]
);
insert into T values
(1, array[null, 42]), -- filled from the start
(2, array[]::int[]); -- we'll fill this later as we get values
update T set list[2] = 42 where id = 2; -- we got a value for id 2 now
select x.* from T, unnest(T.list) with ordinality as x (val, idx) where id = 1;
select x.* from T, unnest(T.list) with ordinality as x (val, idx) where id = 2;
字符串
两个select
的输出为:
val | idx
-----+-----
| 1
42 | 2
val | idx
-----+-----
42 | 1
型
这是不幸的,因为在我的例子中,元素的位置是重要的。第二个查询显示值42的索引为1,这破坏了我正在做的事情。
我很高兴PostgreSQL没有盲目地用NULL
填充未设置的数组索引,因为这可能会保存大量的存储空间(第二个数组存储为[2:2]={42}
而不是{NULL,42}
)。但在这种情况下,这是不方便的。
最好的解决办法是什么?
背景:我们需要存储数十亿个float 8值。它们以EAV格式(实体-属性-值)到达,我们按实体将它们聚合到数组中,属性提供数组索引。这几乎不再是相对合理的了,但是大量的数据很难以其他方式管理。
- 编辑:我不知道为什么StackOverflow一直把“sparse-array”标签改为“sparse-matrix”。这与多维数组无关。*
1条答案
按热度按时间hc8w905p1#
不知道为什么它是documented separately而不是the array functions,但你可以使用
generate_subscripts
函数来实现。与WITH ORDINALITY
不同,它不产生排序,而是产生实际的下标,你可以用它来索引数组:字符串
(online demo)
但是,请注意,Postgres arrays实际上并不是稀疏的-它们只是具有任意的(下限和上限)边界。我不确定这样做的目的是什么-也许它与数组切片的表示方式有关,也许它旨在支持0-based indexing(尽管这会导致more confusion than value),但无论是哪种情况。
[当]赋值给尚未存在的元素[,]之前存在的元素和新赋值的元素之间的任何位置都将填充空值。
如果你真的需要一些稀疏的东西,可以插入任意的键,并且中间没有任何空间,看看hstore或jsonb。