Postgresql 排序数组元素

Postgresql 排序数组元素,postgresql,Postgresql,我想编写一个存储过程,获取一个数组作为输入参数,并对该数组进行排序,然后返回排序后的数组 请帮忙。只需使用unnest()函数即可: 请参阅Pg文档中的。在PostrgreSQL 8.4及更高版本中,您可以使用: select array_agg(x) from (select unnest(ARRAY[1,5,3,7,2]) AS x order by x) as _; 但不会很快 在较老的Postgres中,您可以像这样实现unnest CREATE OR REPLACE FUNCTIO

我想编写一个存储过程,获取一个数组作为输入参数,并对该数组进行排序,然后返回排序后的数组


请帮忙。

只需使用unnest()函数即可:


请参阅Pg文档中的。

在PostrgreSQL 8.4及更高版本中,您可以使用:

select array_agg(x) from (select unnest(ARRAY[1,5,3,7,2]) AS x order by x) as _;
但不会很快


在较老的Postgres中,您可以像这样实现unnest

CREATE OR REPLACE FUNCTION unnest(anyarray)
  RETURNS SETOF anyelement AS
$BODY$
SELECT $1[i] FROM
    generate_series(array_lower($1,1),
                    array_upper($1,1)) i;
$BODY$
  LANGUAGE 'sql' IMMUTABLE
数组_agg如下所示:

CREATE AGGREGATE array_agg (
        sfunc = array_append,
        basetype = anyelement,
        stype = anyarray,
        initcond = '{}'
);
但速度会更慢


您还可以用pl/pgsql或任何其他可以插入postgres的语言实现任何排序算法


请看克雷格的答案,因为他对博士后的知识更为渊博,并且有更好的答案。如果可能的话,请投票删除我的答案。

非常好地展示PostgreSQL的功能是David Fetter排序的一般程序

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(
    SELECT $1[s.i] AS "foo"
    FROM
        generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
    ORDER BY foo
);
$$;

对整数数组进行排序的最佳方法无疑是使用,这比任何SQL公式都快得多:

CREATE EXTENSION intarray;

SELECT sort( ARRAY[4,3,2,1] );
适用于任何数组类型的函数为:

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(SELECT unnest($1) ORDER BY 1)
$$;

(我已将我的版本替换为其他地方讨论后的版本)。

如果您正在寻找一种可以跨任何数据类型工作的解决方案,我建议您采用在中列出的方法

本质上,您可以创建一个存储过程(下面的代码)来为您执行排序,您所需要做的就是将数组传递给该过程,以便对其进行适当排序

我还包括了一个不需要使用存储过程的实现,如果您希望查询更具可移植性的话

创建存储过程

DROP FUNCTION IF EXISTS array_sort(anyarray);
CREATE FUNCTION
  array_sort(
    array_vals_to_sort anyarray
  )
  RETURNS TABLE (
    sorted_array anyarray
  )
  AS $BODY$
    BEGIN
      RETURN QUERY SELECT
        ARRAY_AGG(val) AS sorted_array
      FROM
        (
          SELECT
            UNNEST(array_vals_to_sort) AS val
          ORDER BY
            val
        ) AS sorted_vals
      ;
    END;
  $BODY$
LANGUAGE plpgsql;
-- The following will return: {1,2,3,4}
SELECT ARRAY_SORT(ARRAY[4,3,2,1]);

-- The following will return: {in,is,it,on,up}
SELECT ARRAY_SORT(ARRAY['up','on','it','is','in']);
排序数组值(适用于任何数组数据类型)

不使用存储过程对数组值进行排序

DROP FUNCTION IF EXISTS array_sort(anyarray);
CREATE FUNCTION
  array_sort(
    array_vals_to_sort anyarray
  )
  RETURNS TABLE (
    sorted_array anyarray
  )
  AS $BODY$
    BEGIN
      RETURN QUERY SELECT
        ARRAY_AGG(val) AS sorted_array
      FROM
        (
          SELECT
            UNNEST(array_vals_to_sort) AS val
          ORDER BY
            val
        ) AS sorted_vals
      ;
    END;
  $BODY$
LANGUAGE plpgsql;
-- The following will return: {1,2,3,4}
SELECT ARRAY_SORT(ARRAY[4,3,2,1]);

-- The following will return: {in,is,it,on,up}
SELECT ARRAY_SORT(ARRAY['up','on','it','is','in']);
在以下查询中,只需将
数组[4,3,2,1]
替换为返回数组的数组或查询:

WITH
  sorted_vals AS (
    SELECT
      UNNEST(ARRAY[4,3,2,1]) AS val
    ORDER BY
      val
  )
SELECT
  ARRAY_AGG(val) AS sorted_array
FROM
  sorted_vals
。。。或者

SELECT
  ARRAY_AGG(vals.val) AS sorted_arr
FROM (
  SELECT
    UNNEST(ARRAY[4,3,2,1]) AS val
  ORDER BY
    val
) AS vals

@MartijnPieter注意到它与我的答案是一样的,但我在一年前回答并引用了我从何处得到的答案。@AdamGent:我想我在第一个答案队列中找到了它,只是重新格式化了SQL以使其可读。换句话说,除了不可读的格式之外,我没有任何上下文。最快的方法是
intarray
contrib模块中的
sort
函数。我用一些更现代的技术更新了那篇wiki文章,所以请使用文章中的代码(或查看我的答案),不是这里显示的旧答案。Craig我投票删除了我的答案,但由于某些原因,我无法自行终止;)。因此,我做了一个注释以查看您的答案。如果我没有错,那么上面的
array\u sort()
函数应该在第二个
$$
之后定义为
稳定的
(或者可能是
不可变的
)标记。其他程序员可能会查看这些波动性标签,以获取关于给定函数如何工作的提示<代码>语言SQL-函数(通常)由Postgres内联,但添加标签没有任何害处。请记住,
Unest
将取消对数组的所有级别的测试:因此,如果尝试对数组进行排序,则会得到意外的结果:数组的形状保持不变,但是这些值是单独排序的,不是作为子数组。嗨,bigint没有类似的扩展?它更长,但比Craig的解决方案好吗?我不确定我是否理解你问题的缩进。。是否对您的实现“更好”由您决定。Craig提供了一个5行工作解决方案。差不多一年后,您添加了一个答案,其中包含了一个更长的解决方案。所以我想你的解决方案一定是更好的,或者在某些情况下有效,而另一个则不行。我是(Postgre)SQL新手,所以我无法判断,所以我问:)我还没有进行压力测试来比较我列出的方法和克雷格的方法。。如果有机会,我可能会这么做。:)我确实补充说,排序也可以在不需要创建存储过程的情况下执行,而存储过程对某些人来说可能很有用。不一定是压力测试,但可能是“设计”或其他方面。但如果你不知道,没问题,这只是另一个解决方案,也许其他人稍后会对其中一个发表评论。(