Ответ 1
Postgres 9.3 и старше
Простой zip()
Рассмотрим следующую демонстрацию для Postgres 9.3 или более ранней:
SELECT ARRAY[a,b] AS ab
FROM (
SELECT unnest('{a,b,c}'::text[]) AS a
,unnest('{d,e,f}'::text[]) AS b
) x;
Результат:
ab
-------
{a,d}
{b,e}
{c,f}
Обратите внимание, что оба массива должны иметь одинаковое количество элементов для параллельной печати, или вместо этого вы получаете перекрестное соединение.
Вы можете обернуть это в функцию, если хотите:
CREATE OR REPLACE FUNCTION zip(anyarray, anyarray)
RETURNS SETOF anyarray LANGUAGE SQL AS
$func$
SELECT ARRAY[a,b] FROM (SELECT unnest($1) AS a, unnest($2) AS b) x;
$func$;
Вызов:
SELECT zip('{a,b,c}'::text[],'{d,e,f}'::text[]);
Тот же результат.
zip() для многомерного массива:
Теперь, если вы хотите заполнить этот новый набор массивов в один массив 2-dimenstional, он становится более сложным.
SELECT ARRAY (SELECT ...)
или
SELECT array_agg(ARRAY[a,b]) AS ab
FROM (
SELECT unnest('{a,b,c}'::text[]) AS a
,unnest('{d,e,f}'::text[]) AS b
) x
или
SELECT array_agg(ARRAY[ARRAY[a,b]]) AS ab
FROM ...
приведет к тому же сообщению об ошибке (проверено с помощью pg 9.1.5):
ОШИБКА: не удалось найти тип массива для текста типа данных []
Но есть способ обойти это, как мы разработали в этот близкий вопрос.
Создайте настраиваемую функцию агрегации:
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
,STYPE = anyarray
,INITCOND = '{}'
);
И используйте его следующим образом:
SELECT array_agg_mult(ARRAY[ARRAY[a,b]]) AS ab
FROM (
SELECT unnest('{a,b,c}'::text[]) AS a
,unnest('{d,e,f}'::text[]) AS b
) x
Результат:
{{a,d},{b,e},{c,f}}
Обратите внимание на дополнительный слой ARRAY[]
! Без него и просто:
SELECT array_agg_mult(ARRAY[a,b]) AS ab
FROM ...
Вы получаете:
{a,d,b,e,c,f}
Что может быть полезно для других целей.
Сбросьте еще одну функцию:
CREATE OR REPLACE FUNCTION zip2(anyarray, anyarray)
RETURNS SETOF anyarray LANGUAGE SQL AS
$func$
SELECT array_agg_mult(ARRAY[ARRAY[a,b]])
FROM (SELECT unnest($1) AS a, unnest($2) AS b) x;
$func$;
Вызов:
SELECT zip2('{a,b,c}'::text[],'{d,e,f}'::text[]); -- or any other array type
Результат:
{{a,d},{b,e},{c,f}}
Postgres 9.4 +
Используйте конструкцию ROWS FROM
или обновленный unnest()
, который параллелизирует несколько массивов. Каждая из них может иметь разную длину. Вы получаете (за документацию):
[...] количество строк результата в этом случае - это число наибольшей функции результат с меньшими результатами, дополненными нулевыми значениями, которые будут соответствовать.
Используйте этот более чистый и простой вариант:
SELECT ARRAY[a,b] AS ab
FROM unnest('{a,b,c}'::text[]
, '{d,e,f}'::text[]) x(a,b);
Postgres 9.5 +
отправляет array_agg(array expression)
:
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)
Это замена для моей настраиваемой агрегатной функции array_agg_mult()
, реализованной на C, которая значительно быстрее. Используйте его.