изменить кронштейны для агрегации массива в Postgres

Обновить

December 2018

Просмотры

867 раз

1

Я хотел изменить скобки «{» и «}» на «[» и «]» в следующем примере. У меня есть таблица А с двумя coloumns, один текст_1 типа строки , а второй счетчик типа BIGINT. То , что я пытаюсь сделать , это вернуть матричные обозначения типа [[1,2,4],[2,4,5],...].

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

WITH B AS(
SELECT 
    array_agg(count) AS count 
FROM
    A 
GROUP BY
    text_1
)
SELECT
    array_agg_mult(ARRAY[count]) 
FROM
    B;

Кроме того , как обновить array_agg_mult, если я пытаюсь изменить , INITCOND = '{}'чтобы INITCOND = '[]'я получаю

ОШИБКА: функция «array_agg_mult» уже существует с теми же типами аргументов

Может быть, есть умное решение с использованием поколения JSon с Postgres.

1 ответы

4

Those brackets have nothing to do with the aggregation. Those are just the output format of the array type. A new aggregate function won't change that.

You can verify that by simply doing a

select array[1,2,3]

which will display:

array  
-------
{1,2,3}

The '{}' in the INITCOND simply means "empty array".

See the manual for details: https://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO

The only way to change that display would be to change the output method for arrays in general. I don't think this can be done without hacking the Postgres sources (and which would probably break many things)

If you want to display arrays in a different format, write your own function to do that.

create function format_array(p_array anyarray)
  returns text
as
$$
  select translate(p_array::text, '{}', '[]');
$$
language sql;

Then you can use that on any array:

select format_array(array[1,2,3]), 
       format_array('{}'::int[]), 
       format_array(array[[1,2,3],[4,5,6]]);

will output:

format_array | format_array | format_array     
-------------+--------------+------------------
[1,2,3]      | []           | [[1,2,3],[4,5,6]]

Of course you can apply more "cosmetics" in the format_array() function then just replacing {} with []


Your query would then become:

WITH B AS
(
  SELECT array_agg(count) AS count 
  FROM A 
  GROUP BY text_1
)
SELECT format_array(array_agg_mult(ARRAY[count]))
FROM B;