Подтвердить что ты не робот

Сортировка элементов массива

Я хочу написать хранимую процедуру, которая получает массив в качестве входного параметра и сортирует этот массив и возвращает отсортированный массив.

Просьба помочь.

4b9b3361

Ответ 1

Лучший способ отсортировать массив целых чисел - это, без сомнения, использование расширения 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)
$$;

(Я заменил мою версию чуть чуть позже после обсуждения в другом месте).

Ответ 2

Просто используйте функцию unsest():

SELECT 
    unnest(ARRAY[1,2]) AS x
ORDER BY 
    x DESC;

См. функции массива в документах Pg.

Ответ 3

В 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.

Ответ 4

Это сработало для меня из 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 и имеет лучший ответ. Также, если возможно, проголосуйте, чтобы удалить мой ответ.

Ответ 5

Очень приятная выставка функций 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
);
$$;

Ответ 6

Если вы ищете решение, которое будет работать с любым типом данных, я бы рекомендовал использовать подход, описанный в 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