postgresql: выбрать массив - PullRequest
4 голосов
/ 10 июля 2011

У меня есть таблица, которая выглядит следующим образом:

 id |   t   
----+-------
  1 | {1,2}
  2 | {5,2}
  3 | {6,2}
  4 | {1,7}
  5 | {1,8}
  6 | {1,9}

Я ищу запрос SELECT, который вернет мне массив t, как {{1,2}, {5,2}, ... {1,9}}.

Если бы t не был типом данных массива, это было бы просто:

SELECT ARRAY (SELECT t from tbl_foo);

То же самое можно сделать, если тип данных int[]?

1 Ответ

4 голосов
/ 11 июля 2011

Я не знаю, есть ли какой-нибудь более простой способ (я надеюсь, что так), но это работает (PostgreSQL не имеет массива массивов, поэтому array_agg aproach здесь не работает):

CREATE OR REPLACE FUNCTION func()
RETURNS int[] AS $$
DECLARE
    arr int[];
    res int[];
    n int;  
BEGIN
    res := '{{0, 0}}';
    FOR arr IN SELECT t FROM tbl_foo
    LOOP
        res := res || arr;
    END LOOP;
    n := array_length(res, 1);
    RETURN res[2:n];
END $$
LANGUAGE 'plpgsql';

Пример:

CREATE TABLE tbl_foo (id serial, t int[]);
INSERT INTO tbl_foo (t) VALUES
    ('{1, 2}'),
    ('{5, 2}'),
    ('{6, 2}'),
    ('{1, 7}'),
    ('{1, 8}'),
    ('{1, 9}');

SELECT func();
                 func                  
---------------------------------------
 {{1,2},{5,2},{6,2},{1,7},{1,8},{1,9}}
(1 row)

EDIT:

Второе решение основано на новой агрегатной функции, которая называется, скажем, array2_agg:

CREATE OR REPLACE FUNCTION array2_agg_cutFirst(res anyarray)
RETURNS anyarray AS $$ 
BEGIN
    RETURN res[2:array_length(res, 1)];
END $$
LANGUAGE 'plpgsql';

CREATE AGGREGATE array2_agg(anyarray)
(
    SFUNC = array_cat,
    STYPE = anyarray,
    FINALFUNC = array2_agg_cutFirst,
    INITCOND = '{{0, 0}}'
);

SELECT array2_agg(t) FROM tbl_foo;
              array2_agg
---------------------------------------
 {{1,2},{5,2},{6,2},{1,7},{1,8},{1,9}}
(1 row)

Мне нужна эта array2_agg_cutFirst функция (просто обрезка первого '{0, 0}' подмассива), потому что INITCOND = '{{}}' недопустим.

...