Сортировка элементов массива - PullRequest
28 голосов
/ 26 мая 2010

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

Пожалуйста, помогите.

Ответы [ 6 ]

39 голосов
/ 13 октября 2012

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

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

14 голосов
/ 26 мая 2010

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

11 голосов
/ 26 мая 2010

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

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

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

7 голосов
/ 10 марта 2011

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

3 голосов
/ 25 мая 2012

Отличная демонстрация возможностей 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
);
$$;
1 голос
/ 09 июля 2013

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