【问题标题】:How to sort two dimensional int array in PostgreSQL?如何在 PostgreSQL 中对二维 int 数组进行排序?
【发布时间】:2015-08-31 10:08:38
【问题描述】:
{{5,23}, {8,45}, {1,12}}

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

{{<b>1</b>,12}, {<b>5</b>,23}, {<b>8</b>,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;

感谢欧文:)

【问题讨论】:

  • 一如既往地,请使用您的 Postgres 版本。您是从表行中获取值还是只处理单个值?
  • @Erwin Brandstetter 9.4 我正在从表行中获取值...我将对每一行中的数组值进行排序,然后以排序方式对其进行更新。

标签: sql arrays database postgresql sorting


【解决方案1】:

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 或更早版本

聚合函数

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

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] 返回每​​个数组切片中的第一个切片,它定义了排序顺序。对于严格的二维数组,您也可以使用arr[i][lo2] 来返回每个切片的第一个元素,但前者适用于大于1 的任何 维。

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

【讨论】:

    【解决方案2】:

    从 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
    

    【讨论】:

      猜你喜欢
      • 2013-09-13
      • 2013-08-17
      • 2021-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-25
      • 2015-09-17
      相关资源
      最近更新 更多