Как отсортировать двухмерный массив int в PostgreSQL?

{{5,23}, {8,45}, {1,12}}

Я хочу отсортировать этот массив в соответствии с первым элементом каждого элемента подмассива, как;

{{1,12}, {5,23}, {8,45}}

Как я могу это сделать?

Редактировать:

Этот код работает;

create or replace function arraysortingaccordingfirstindexofsubarrayelements()
returns void as $$
declare samplearraydata integer[][];
declare sortedarraydata int[][];
begin
samplearraydata:=ARRAY[[5,8], [1,6],[3,9]];
EXECUTE 'CREATE TEMP TABLE temptable (
   firstindex integer,
   secondindex integer
) on commit drop;';
WITH
    data as (select samplearraydata as arr) 
insert into temptable select   
    arr[i][1], 
    arr[i][2] FROM data, 
    generate_subscripts((SELECT arr FROM data), 1) i 
    order by 1;
sortedarraydata:=(SELECT array_agg_mult(ARRAY[ARRAY[y.firstindex, y.secondindex]])) FROM   temptable y;
raise notice '%', sortedarraydata;
end;
$$ language plpgsql;

CREATE AGGREGATE array_agg_mult (anyarray)  (
    SFUNC     = array_cat
   ,STYPE     = anyarray
   ,INITCOND  = '{}'
);

CREATE TEMP TABLE arrtbl (
   firstindex integer,
   secondindex integer
) on commit drop;

Кредиты Эрвину:)

2 ответа

Решение

Postgres 9.5 или новее

корабли с вариантом array_agg() который служит заменой для произвольной функции агрегирования array_agg_mult() ниже - и значительно быстрее. Руководство:

Function                Argument Type(s)   Return Type
array_agg(expression)   any array type     same as argument data type  

Description
input arrays concatenated into array of one higher dimension
(inputs must all have same dimensionality, and cannot be empty or NULL)

Postgres 9.4 или старше

Агрегатная функция

Встроенная агрегатная функция array_agg() в настоящее время (Postgres 9.4) работает только для входных данных не массивов. Поскольку мы собираемся собирать массивы, нам нужна настраиваемая функция агрегирования, как подробно описано в следующем ответе:

CREATE AGGREGATE array_agg_mult (anyarray) (
   SFUNC     = array_cat
 , STYPE     = anyarray
 , INITCOND  = '{}'
);

Доступ к массиву

Требуется базовое понимание синтаксиса массива / как получить доступ к массивам. Прочтите эту главу руководства, если вы еще не там.

запрос

Затем, основываясь на той же настройке, что и этот более ранний ответ сегодня (вы можете прочитать и этот):

SELECT arrtbl_id
     , array_agg_mult(arr[i:i][lo2:up2] ORDER BY arr[i:i][lo2])
FROM  (SELECT arrtbl_id, arr
            , array_lower(arr, 2) AS lo2
            , array_upper(arr, 2) AS up2
       FROM   arrtbl) t
     , generate_subscripts(t.arr, 1) i
GROUP  BY 1;

объяснение

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

    Я не просто начинаю с индекса 1, чтобы охватить возможный угловой случай. Postgres допускает нестандартные подписки на массивы:

  2. LATERAL присоединиться к основному столу generate_subscripts(arr,1) чтобы получить первый индекс для каждого подмассива (независимо от того, сколько измерений).

  3. Выражение arr[i:i][lo2:up2] (или просто arr[i:i][:] в стр 9.6+) возвращает каждый срез массива, сохраняя размеры. Это работает для любого количества элементов и размеров (больше 1).

  4. Выражение arr[i:i][lo2] возвращает первый срез в каждом срезе массива, который определяет порядок сортировки. Для строго 2-х мерных массивов вы можете использовать arr[i][lo2] вернуть первый элемент каждого среза, но первый работает для любой размерности больше 1.

  5. Агрегировать с array_agg_mult() который с радостью принимает значения соответствующего измерения (все хорошо встает на свои места).

Начиная с Postgres 9.4, если вы можете разбить ваш двумерный массив на два одномерных массива, вы можете использовать оператор

unnest(anyarray, anyarray [, ...])

Пример:

SELECT * FROM unnest(ARRAY[6,4,3,5], ARRAY[64,2,1,-1], ARRAY[45,2,4,6]) ORDER BY 1

Вернуть:

4   2   2
3   1   4
5   -1  6
6   64  45

Если вы хотите отсортировать по третьему элементу, вы должны изменить

... ORDER BY 3
Другие вопросы по тегам