Сортировка элементов массива
Я хочу написать хранимую процедуру, которая получает массив в качестве входного параметра и сортирует этот массив и возвращает отсортированный массив.
Пожалуйста, помогите.
7 ответов
Лучший способ сортировки массива целых чисел - без сомнения, использовать расширение 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)
$$;
(Я заменил свою версию чуть более быстрой версией Павла после обсуждения в другом месте).
В 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
И array_agg так:
CREATE AGGREGATE array_agg (
sfunc = array_append,
basetype = anyelement,
stype = anyarray,
initcond = '{}'
);
Но это будет еще медленнее.
Вы также можете реализовать любой алгоритм сортировки в pl/pgsql или любом другом языке, который вы можете подключить к postgres.
Просто используйте функцию unnest():
SELECT
unnest(ARRAY[1,2]) AS x
ORDER BY
x DESC;
Смотрите функции массива в документации Pg.
Это сработало для меня из http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I
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
Я удивлен, что никто не упомянул операторов сдерживания:
select array[1,2,3] <@ array[2,1,3] and array[1,2,3] @> array[2,1,3];
?column?
══════════
t
(1 row)
Обратите внимание, что для этого требуется, чтобы все элементы массивов были уникальными.
(Если a содержит b, а b содержит a, они должны быть одинаковыми, если все элементы уникальны)