PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Има ли нещо като функция zip() в PostgreSQL, която комбинира два масива?

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}}


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изпълнете заявка с LIMIT/OFFSET и получете общия брой редове

  2. Получаване на име на текущата функция вътре във функцията с plpgsql

  3. Не мога да се свържа с PostgreSQL с PHP pg_connect()

  4. Върнете нула, ако не бъде намерен запис

  5. Как мога да импортирам данни от ASCII (ISO/IEC 8859-1) в моята база данни Rails/PGSQL?