我想对数组进行排序。 Postgresql数组运算符如<或者>首先比较它们,然后是第二个成员,依此类推。这不是我想要的。我想要的是阵列,其成员尽可能大且相等。例如: 我们有
[1,2,3]
[2,2,1]
[2,2,2]
排序结果
[2,2,2]
[2,2,1]
[1,2,3]
为了达到这个目的,我设想了一个功能 1.按升序对每个数组进行排序。 2.按此顺序划分每个成员以获取浮动。例如
1/2/2 = 0.25.
1/2/3 = 0.16.
2/2/2 = 1
将第二个动作的结果乘以数组成员的总和。
如何使用reqular sql并且不使用相当慢的循环? 或者可能有人知道在postgresql中权衡数组的更好方法? 任何帮助将不胜感激。
为了澄清这个问题,我应该编写表格结构
CREATE TABLE array_example (
int_array integer[]
);
并要求:
insert into array_example values ('{1,2,3}'), ('{2,2,2}'), ('{2,2,1}');
select * from array_example order by int_array desc
它会给我上面描述的排序结果。 但是如果我添加额外的行
insert into array_example values ('{3,2,1}');
它将是第一个,这不是我想要的,所以按顺序使用另一个数学...最后插入的行必须在第三个第四个位置。
答案 0 :(得分:1)
如果你安装here,我认为这很容易做到:
with sorted as (
select int_array, sort(int_array) as sarray
from array_example
)
select int_array
from sorted
order by (sarray[1]::decimal / sarray[2]::decimal / sarray[3]::decimal) * (sarray[1] + sarray[2] + sarray[3]);
请注意,上面没有错误检查:即没有值等于零(会导致除零错误),如果数组不总是包含(至少)三个元素,它也会产生null
。
当然你可以将公式(和排序)包装成一个函数,这会使查询更短:
create or replace function array_weight(p_array int[])
returns decimal
as
$$
declare
l_sorted int[];
begin
l_sorted := sort(p_array);
return (l_sorted[1]::decimal / l_sorted[2]::decimal / l_sorted[3]::decimal) * (l_sorted[1] + l_sorted[2] + l_sorted[3]);
end;
$$
language plpgsql
immutable;
然后使用:
select *
from array_example
order by array_weight(int_array) desc;
可以在没有intarray模块的情况下完成数组的排序,但我不希望有一个好的表现:
create or replace function array_weight(p_array int[])
returns decimal
as
$$
declare
l_sorted int[];
begin
select array_agg(i order by i)
into l_sorted
from (select unnest(p_array) i) t;
return (l_sorted[1]::decimal / l_sorted[2]::decimal / l_sorted[3]::decimal) * (l_sorted[1] + l_sorted[2] + l_sorted[3]);
end;
$$
language plpgsql
immutable;