I want to write a stored procedure that gets an array as input parameter and sort that array and return the sorted array.
7 Answers
The best way to sort an array of integers is without a doubt to use the intarray extension, which will do it much, much, much faster than any SQL formulation:
CREATE EXTENSION intarray;
SELECT sort( ARRAY[4,3,2,1] );
A function that works for any array type is:
CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(SELECT unnest($1) ORDER BY 1)
$$;
(I've replaced my version with Pavel's slightly faster one after discussion elsewhere).

- 307,061
- 76
- 688
- 778
-
Craig I voted to delete my answer but for some reason I can't self terminate ;) . Thus I made a note to see your answer. – Adam Gent Sep 17 '13 at 01:59
-
If I'm not wrong, the `array_sort()` function above should be defined with the `STABLE` (or perhaps `IMMUTABLE`) tag after the second `$$`. Other programmers may look at such volatility-labels for hints about how a given function works. `LANGUAGE SQL`-functions are (typically) inlined by Postgres, but there's no harm in adding the label either way. – Seldom 'Where's Monica' Needy Dec 18 '15 at 07:10
-
2Keep in mind that `unnest` will unnest all levels of an array: so if you are trying to sort an array of arrays, then you will have unexpected results: the shape of the arrays are maintained, but the values are sorted individually, not as a sub-array. – Matthew Schinckel Apr 27 '17 at 07:09
-
5Hi, there are no similar extension for **bigint**? – Peter Krauss Aug 13 '18 at 08:37
In PostrgreSQL 8.4 and up you can use:
select array_agg(x) from (select unnest(ARRAY[1,5,3,7,2]) AS x order by x) as _;
But it will not be very fast.
In older Postgres you can implement unnest like this
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
And array_agg like this:
CREATE AGGREGATE array_agg (
sfunc = array_append,
basetype = anyelement,
stype = anyarray,
initcond = '{}'
);
But it will be even slower.
You can also implement any sorting algorithm in pl/pgsql or any other language you can plug in to postgres.

- 22,573
- 5
- 59
- 73
-
1The fastest way is the `sort` function in the `intarray` contrib module. – Craig Ringer Oct 13 '12 at 06:12
-
The first solution could be written equivalently, and much more concisely, as `SELECT array_agg(x ORDER BY x) FROM unnest(ARRAY[1,5,3,7,2]) AS x;` – Spencer Mathews May 12 '23 at 04:56
Just use the function unnest():
SELECT
unnest(ARRAY[1,2]) AS x
ORDER BY
x DESC;
See array functions in the Pg docs.

- 307,061
- 76
- 688
- 778

- 117,544
- 24
- 142
- 135
This worked for me from http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I#General_array_sort
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
);
$$;
Please see Craig's answer since he is far more more knowledgable on Postgres and has a better answer. Also if possible vote to delete my answer.

- 47,843
- 23
- 153
- 203
-
1I got that wiki article updated with some more modern techniques, so please use the code in the article (or see my answer), not the older one shown here. – Craig Ringer Oct 14 '12 at 03:37
Very nice exhibition of PostgreSQL's features is general procedure for sorting by 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
);
$$;

- 1,048,767
- 296
- 4,058
- 3,343

- 846
- 8
- 24
-
@MartijnPieters Notice how its the same answer as mine but I answered a year ago and referenced where I got it from. – Adam Gent Sep 26 '12 at 20:19
-
1@AdamGent: I think I found this in the first answer queue and only reformatted the SQL to make it readable. In other words, I didn't have any context other than unreadable formatting. – Martijn Pieters Sep 26 '12 at 20:23
If you're looking for a solution which will work across any data-type, I'd recommend taking the approach laid out at YouLikeProgramming.com.
Essentially, you can create a stored procedure (code below) which performs the sorting for you, and all you need to do is pass your array to that procedure for it to be sorted appropriately.
I have also included an implementation which does not require the use of a stored procedure, if you're looking for your query to be a little more transportable.
Creating the stored procedure
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;
Sorting array values (works with any array data-type)
-- 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']);
Sorting array values without a stored procedure
In the following query, simply replace ARRAY[4,3,2,1]
with your array or query which returns an array:
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
... or ...
SELECT
ARRAY_AGG(vals.val) AS sorted_arr
FROM (
SELECT
UNNEST(ARRAY[4,3,2,1]) AS val
ORDER BY
val
) AS vals

- 8,268
- 4
- 48
- 61
-
-
I'm not sure I understand the indent of your question.. Whether it's "better" for your implementation is up for you to decide. – Joshua Burns Oct 02 '14 at 19:55
-
Well, Craig provides a 5 lines working solution. Almost one year later, you add an answer with a much longer solution. So I guess your solution must be somehow better, or work in some cases where the other doesn't. I'm a (Postgre)SQL newbie, so I can't judge, therefore I ask. :) – Skippy le Grand Gourou Oct 02 '14 at 20:06
-
I haven't ran a stress test to compare the method I've listed vs. Craig's.. If I get a chance, I might just do that though. :) I did add that sorting can also be performed without the need of creating a stored procedure which may be useful to some. – Joshua Burns Oct 06 '14 at 02:06
-
Right, of course I was just referring to the stored procedure. Not necessarily in terms of a stress test, but possibly in terms of "design" or whatever. But if you don't know, no problem, it's just another solution, maybe someone else will come later to comment on one or the other. ;) – Skippy le Grand Gourou Oct 06 '14 at 09:03
I'm surprised no-one has mentioned the containment operators:
select array[1,2,3] <@ array[2,1,3] and array[1,2,3] @> array[2,1,3];
?column?
══════════
t
(1 row)
Notice that this requires that all elements of the arrays must be unique.
(If a contains b and b contains a, they must be the same if all elements are unique)

- 1,298
- 1
- 10
- 18
-
Not true - select array[1, 1, 1, 1, 1, 2, 3, 3 ,2,3] <@ array[2,1,3] and array[1,2,3] @> array[2,1,3]; Result t - see fiddle [here](https://stackoverflow.com/questions/2913368/sorting-array-elements). – Vérace Jan 29 '23 at 03:04