我正在尋找一種經過查詢來鏈接一個組內字段字符串的方法。 例如,我有一張桌子: php
ID COMPANY_ID EMPLOYEE 1 1 Anna 2 1 Bill 3 2 Carol 4 2 Dave
我想按company_id分組以獲取相似信息: html
COMPANY_ID EMPLOYEE 1 Anna, Bill 2 Carol, Dave
mySQL中有一個內置函數來執行此group_concat sql
再次使用字符串鏈接的自定義聚合函數:您須要記住,select語句將以任何順序放置行,所以您須要在from語句中使用order by子句進行子選擇 ,而且而後使用帶有group by子句的外部select來聚合字符串,所以: 數據庫
SELECT custom_aggregate(MY.special_strings) FROM (SELECT special_strings, grouping_column FROM a_table ORDER BY ordering_column) MY GROUP BY MY.grouping_column
如何使用Postgres內置數組函數? 至少在8.4上能夠當即使用: express
SELECT company_id, array_to_string(array_agg(employee), ',') FROM mytable GROUP BY company_id;
如前所述,建立本身的聚合函數是正確的事情。 這是個人串聯聚合函數(您能夠在法語中找到詳細信息 ): 數組
CREATE OR REPLACE FUNCTION concat2(text, text) RETURNS text AS ' SELECT CASE WHEN $1 IS NULL OR $1 = \'\' THEN $2 WHEN $2 IS NULL OR $2 = \'\' THEN $1 ELSE $1 || \' / \' || $2 END; ' LANGUAGE SQL; CREATE AGGREGATE concatenate ( sfunc = concat2, basetype = text, stype = text, initcond = ''
); app
而後將其用做: 函數
SELECT company_id, concatenate(employee) AS employees FROM ...
我對這個答案不屑一顧,由於我通過一番搜索發現了它: post
我不知道的是PostgreSQL容許您使用CREATE AGGREGATE定義本身的聚合函數 測試
PostgreSQL列表上的該帖子顯示了建立一個函數來執行所需的操做是多麼簡單:
CREATE AGGREGATE textcat_all( basetype = text, sfunc = textcat, stype = text, initcond = '' ); SELECT company_id, textcat_all(employee || ', ') FROM mytable GROUP BY company_id;
Postgres的最新版本(自2010年底開始)具備string_agg(expression, delimiter)
函數,該函數將徹底執行問題的要求,甚至容許您指定分隔符字符串:
SELECT company_id, string_agg(employee, ', ') FROM mytable GROUP BY company_id;
Postgres 9.0還增長了在任何聚合表達式中指定ORDER BY
子句的功能; 不然,順序是不肯定的。 所以,您如今能夠編寫:
SELECT company_id, string_agg(employee, ', ' ORDER BY employee) FROM mytable GROUP BY company_id;
或者確實是:
SELECT string_agg(actor_name, ', ' ORDER BY first_appearance)
PostgreSQL 8.4(2009年)引入了聚合函數array_agg(expression)
,該函數將值鏈接到一個數組中。 而後可使用array_to_string()
給出所需的結果:
SELECT company_id, array_to_string(array_agg(employee), ', ') FROM mytable GROUP BY company_id;
string_agg
: 若是有人遇到這種狀況,但願在9.0以前版本的數據庫中找到兼容的填充程序,則能夠在string_agg
實現除ORDER BY
子句之外的全部內容。
所以,使用如下定義,該方法應與9.x Postgres DB中的相同:
SELECT string_agg(name, '; ') AS semi_colon_separated_names FROM things;
但這將是語法錯誤:
SELECT string_agg(name, '; ' ORDER BY name) AS semi_colon_separated_names FROM things; --> ERROR: syntax error at or near "ORDER"
已在PostgreSQL 8.3上測試。
CREATE FUNCTION string_agg_transfn(text, text, text) RETURNS text AS $$ BEGIN IF $1 IS NULL THEN RETURN $2; ELSE RETURN $1 || $3 || $2; END IF; END; $$ LANGUAGE plpgsql IMMUTABLE COST 1; CREATE AGGREGATE string_agg(text, text) ( SFUNC=string_agg_transfn, STYPE=text );
在9.0以前,沒有內置的聚合函數來鏈接字符串。 最簡單的自定義實現( 由Vajda Gabo在此郵件列表中的建議中 ,以及其餘不少建議)是使用內置的textcat
函數(位於||
運算符以後):
CREATE AGGREGATE textcat_all( basetype = text, sfunc = textcat, stype = text, initcond = '' );
這只是將全部琴絃粘在一塊兒,沒有分隔符。 爲了使它們之間沒有插入「,」,您可能想要建立本身的串聯函數,並將其替換爲上面的「 textcat」。 這是我整理並在8.3.12上測試過的一個:
CREATE FUNCTION commacat(acc text, instr text) RETURNS text AS $$ BEGIN IF acc IS NULL OR acc = '' THEN RETURN instr; ELSE RETURN acc || ', ' || instr; END IF; END; $$ LANGUAGE plpgsql;
即便該行中的值爲null或爲空,此版本也會輸出逗號,所以您將得到以下輸出:
a, b, c, , e, , g
若是您但願刪除多餘的逗號以輸出此內容:
a, b, c, e, g
而後將ELSIF
檢查添加到以下函數:
CREATE FUNCTION commacat_ignore_nulls(acc text, instr text) RETURNS text AS $$ BEGIN IF acc IS NULL OR acc = '' THEN RETURN instr; ELSIF instr IS NULL OR instr = '' THEN RETURN acc; ELSE RETURN acc || ', ' || instr; END IF; END; $$ LANGUAGE plpgsql;