Я хочу написать хранимую процедуру, которая получает массив в качестве входного параметра и сортирует этот массив и возвращает отсортированный массив.
Просьба помочь.
Я хочу написать хранимую процедуру, которая получает массив в качестве входного параметра и сортирует этот массив и возвращает отсортированный массив.
Просьба помочь.
Лучший способ отсортировать массив целых чисел - это, без сомнения, использование расширения intarray, которое будет делать это намного, намного, намного быстрее, чем любая формулировка 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)
$$;
(Я заменил мою версию чуть чуть позже после обсуждения в другом месте).
Просто используйте функцию unsest():
SELECT
unnest(ARRAY[1,2]) AS x
ORDER BY
x DESC;
См. функции массива в документах Pg.
В PostrgreSQL 8.4 и выше вы можете использовать:
select array_agg(x) from (select unnest(ARRAY[1,5,3,7,2]) AS x order by x) as _;
Но это будет не очень быстро.
В более старых Postgres вы можете реализовать такие неприятные ощущения
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
И array_agg вот так:
CREATE AGGREGATE array_agg (
sfunc = array_append,
basetype = anyelement,
stype = anyarray,
initcond = '{}'
);
Но он будет еще медленнее.
Вы также можете реализовать любой алгоритм сортировки в pl/pgsql или любом другом языке, который вы можете подключить к postgres.
Это сработало для меня из 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
);
$$;
Пожалуйста, см. ответ Крейга, поскольку он гораздо более осведомлен о Postgres и имеет лучший ответ. Также, если возможно, проголосуйте, чтобы удалить мой ответ.
Очень приятная выставка функций PostgreSQL - это общая процедура сортировки Дэвида Феттера.
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
);
$$;
Если вы ищете решение, которое будет работать с любым типом данных, я бы рекомендовал использовать подход, описанный в YouLikeProgramming.com.
По существу, вы можете создать хранимую процедуру (код ниже), которая выполняет сортировку для вас, и все, что вам нужно сделать, - передать ваш массив этой процедуре, чтобы она была правильно отсортирована.
Я также включил реализацию, которая не требует использования хранимой процедуры, если вы ищете, чтобы ваш запрос был немного более переносимым.
Создание хранимой процедуры
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']);
Сортировка значений массива без хранимой процедуры
В следующем запросе просто замените ARRAY[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