如何在PostgreSQL中对二维int数组进行排序?

时间:2015-06-15 19:12:12

标签: sql arrays database postgresql sorting

{{5,23}, {8,45}, {1,12}}

我想根据每个子数组元素的第一个元素对这个数组进行排序,比如;

{{1,12}, {5,23}, {8,45}}

我该怎么做?

修改:

此代码有效;

create or replace function arraysortingaccordingfirstindexofsubarrayelements()
returns void as $$
declare samplearraydata integer[][];
declare sortedarraydata int[][];
begin
samplearraydata:=ARRAY[[5,8], [1,6],[3,9]];
EXECUTE 'CREATE TEMP TABLE temptable (
   firstindex integer,
   secondindex integer
) on commit drop;';
WITH
    data as (select samplearraydata as arr) 
insert into temptable select   
    arr[i][1], 
    arr[i][2] FROM data, 
    generate_subscripts((SELECT arr FROM data), 1) i 
    order by 1;
sortedarraydata:=(SELECT array_agg_mult(ARRAY[ARRAY[y.firstindex, y.secondindex]])) FROM   temptable y;
raise notice '%', sortedarraydata;
end;
$$ language plpgsql;

CREATE AGGREGATE array_agg_mult (anyarray)  (
    SFUNC     = array_cat
   ,STYPE     = anyarray
   ,INITCOND  = '{}'
);

CREATE TEMP TABLE arrtbl (
   firstindex integer,
   secondindex integer
) on commit drop;

对Erwin的信任:)

2 个答案:

答案 0 :(得分:2)

Postgres 9.5或更新版

附带array_agg()的变体,可作为下方自定义汇总函数array_agg_mult()的替代品 - 并且速度相当快。 The manual:

  
Function                Argument Type(s)   Return Type
array_agg(expression)   any array type     same as argument data type  

Description
input arrays concatenated into array of one higher dimension
(inputs must all have same dimensionality, and cannot be empty or NULL)

Postgres 9.4或更早

聚合函数

当前内置的聚合函数array_agg()(Postgres 9.4)仅适用于非数组输入数据类型。由于我们要聚合数组,我们需要一个自定义聚合函数,如相关答案中详述的那样:

CREATE AGGREGATE array_agg_mult (anyarray) (
   SFUNC     = array_cat
 , STYPE     = anyarray
 , INITCOND  = '{}'
);

访问数组

需要基本了解数组语法/如何访问数组。如果您不在,请阅读this chapter of the manual

查询

然后,基于与今天早期答案相同的设置(您可能也想阅读那个):

SELECT arrtbl_id
     , array_agg_mult(arr[i:i][lo2:up2] ORDER BY arr[i:i][lo2])
FROM  (SELECT arrtbl_id, arr
            , array_lower(arr, 2) AS lo2
            , array_upper(arr, 2) AS up2
       FROM   arrtbl) t
     , generate_subscripts(t.arr, 1) i
GROUP  BY 1;

解释

  1. 计算基表中第二个数组维度的下限和上限,这比为每个数组切片重复它要便宜。

    我不是简单地从索引1开始来涵盖可能的角落案例。 Postgres允许非标准数组下标:

  2. LATERAL将基表连接到generate_subscripts(arr,1)以获取每个子数组的第一个索引(无论维数多少)。

  3. 表达式arr[i:i][lo2:up2](或pg 9.6+中的arr[i:i][:])返回每个保留维度的数组切片。 适用于任意数量的元素和维度(大于1)。

  4. 表达式arr[i:i][lo2]返回每个数组切片中的第一个切片,它定义了排序顺序。对于严格的2-dimnesional数组,您也可以使用arr[i][lo2]返回每个切片的第一个元素,但前者适用于大于1的任何维度

  5. array_agg_mult()聚合,乐意接受适当维度的值(一切都很好地落实到位)。

答案 1 :(得分:0)

自Postgres 9.4以来,如果你可以将二维数组分解为两个一维数组,你可以使用运算符

unnest(anyarray, anyarray [, ...])

示例:

SELECT * FROM unnest(ARRAY[6,4,3,5], ARRAY[64,2,1,-1], ARRAY[45,2,4,6]) ORDER BY 1

返回:

4   2   2
3   1   4
5   -1  6
6   64  45

如果你想按第三元素排序,你应该改变

... ORDER BY 3