postgresql数组比较使用权重函数或类似的东西

时间:2015-05-18 10:27:33

标签: arrays postgresql sorting

我想对数组进行排序。 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
  1. 将第二个动作的结果乘以数组成员的总和。

    • 1 * 6 = 6
    • 0.25 * 5 = 1.25
    • 0.16 * 6 = 0.96
  2. 如何使用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}');
    

    它将是第一个,这不是我想要的,所以按顺序使用另一个数学...最后插入的行必须在第三个第四个位置。

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;