Измените агрегат «список» postgresql, чтобы удалить дубликаты.
-
05-09-2019 - |
Вопрос
Один из моих любимых агрегатов postgres — «list», приписываемый «Крису Рольфсу в idocs», согласно скудным свидетельствам, которые я могу найти в Интернете.
CREATE FUNCTION comma_cat (text, text)
RETURNS text AS
'SELECT CASE
WHEN $2 is null or $2 = '''' THEN $1
WHEN $1 is null or $1 = '''' THEN $2
ELSE $1 || '', '' || $2
END'
LANGUAGE sql;
CREATE AGGREGATE list (BASETYPE = text, SFUNC = comma_cat, STYPE = text, INITCOND = '');
Иногда я обнаруживаю, что мне хотелось бы устранить дубликаты.Ан старая ветка списка рассылки предполагает, что этот подход не может выполнять сортировку, что может помешать удалению дубликатов. Еще один пост в той же теме предлагает функцию, которая делает то же самое;может быть, это более модифицируемо для этой цели?
А пока я просто массирую вывод на другом языке.Но было бы здорово, если бы мы могли сделать это прямо в postgres!
Решение
Вы можете использовать промежуточные массивы:
CREATE OR REPLACE FUNCTION comma_cat(text[], text)
RETURNS text[] AS
$BODY$
SELECT
CASE WHEN $1 @> ARRAY[$2] THEN $1
ELSE $1 || $2
END
$BODY$
LANGUAGE 'sql' VOLATILE;
CREATE OR REPLACE FUNCTION comma_finish(text[])
RETURNS text AS
$BODY$
SELECT array_to_string($1, ', ')
$BODY$
LANGUAGE 'sql' VOLATILE
COST 100;
CREATE AGGREGATE list (BASETYPE = text, SFUNC = comma_cat, STYPE = text[], FINALFUNC = comma_finish, INITCOND = '{NULL, NULL}');
value id
-------- --
"puer" 1
"socer" 2
"vesper" 3
"vesper" 4
"gener" 5
"asper" 6
"asper" 7
"miser" 8
"tener" 9
"liber" 10
"puer" 11
SELECT list(value)
FROM t_text
"puer, vesper, gener, asper, miser, tener, liber, socer"
Другие советы
вы можете просто поместить квалификатор «отличный» внутри вызова агрегатной функции, чтобы удалить дубликаты:
select list(distinct <column>)
from...