Postgres 9.5 или по-нова версия
има array_agg(array expression)
:
array_agg
(anyarray
) →anyarray
Конкатенира всички входни масиви в масив с едно по-високо измерение. (Всичките входове трябва да имат еднаква размерност и не могат да бъдат празни или нулеви.)
Това е добавен заместител на моята персонализирана агрегатна функция array_agg_mult()
демонстрирано по-долу. Реализиран е на C и значително по-бърз. Използвайте го.
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.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-измерен масив, става по-сложно.
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):
ГРЕШКА:не можа да се намери тип масив за тип данни text[]
Но има начин да заобиколите това, както разработихме по този тясно свързан въпрос.
Създайте персонализирана агрегатна функция:
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}}