2009-02-18 2 views
1

Один из моих любимых агрегатов postgres - это «список», приписываемый «Chris Rohlfs в idocs» в соответствии с скудными доказательствами, которые я могу найти в Интернете.Изменить postgresql "list" aggregate для удаления дубликатов

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 = ''); 

Я нахожу, иногда, что хотел бы его устранить дубликаты. old mailing list thread предполагает, что этот подход не может выполнять сортировку, что может быть убийцей сделок для удаления дубликатов. Another post in the same thread предлагает функцию, которая делает то же самое; возможно, это более изменчиво для этой цели?

А пока я просто массирую вывод на другом языке. Но было бы здорово, если бы мы могли сделать это прямо в postgres!

+0

Смотрите обновленный пост – Quassnoi

+0

Переехал из редактирования: К сожалению, , Первоначальный подход Кваснуи, похоже, не помог; У меня есть тот же список результатов из нового метода, который я получаю от того, что я использовал изначально. Я действительно пытался добавить КОГДА $ 1 = $ 2 ТОГДА $ 1 изначально, хотя я не знал о SORTOP. –

ответ

3

Вы можете использовать промежуточные массивы:

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" 
+0

Ah ha; теперь это работает, хотя мне пришлось удалить COST 100, потому что он дал мне синтаксическую ошибку (postgresql 8.2.3). Благодаря тонну. Теперь мне нужно найти хорошую ссылку на создание функций и агрегатов, чтобы я мог понять, что он делает! –

+0

Ну, первый хит google на «posgresql create aggregate» дает следующее: http://www.postgresql.org/docs/8.1/interactive/sql-createaggregate.html :) – Quassnoi

+0

О, определенно; это будет моя первая остановка. Еще раз спасибо! –

3

вы можете просто поставить «отчетливый» спецификатор внутри вызова агрегатной функции для удаления дубликатов:

select list(distinct <column>) 
from... 
+0

Это отлично работает для меня .... спасибо ... –

Смежные вопросы