如何通过查询连接PostgreSQL'组中的string字段的string?

我正在寻找一种方法来连接组中的一个字段的string查询。 举个例子,我有一个表格:

ID COMPANY_ID EMPLOYEE 1 1 Anna 2 1 Bill 3 2 Carol 4 2 Dave 

我想通过company_id进行分组,得到如下所示的内容:

 COMPANY_ID EMPLOYEE 1 Anna, Bill 2 Carol, Dave 

在mySQL中有一个内置函数来执行这个group_concat

从PostgreSQL 9.0开始更新:

Postgres的最新版本(自2010年底以来)具有string_agg(expression, delimiter)函数,它将完成所要求的问题,甚至可以指定分隔符string:

 SELECT company_id, string_agg(employee, ', ') FROM mytable GROUP BY company_id; 

从PostgreSQL 8.4开始更新:

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; 

原始答案(对于8.4之前的PostgreSQL):

没有内置的聚合函数来连接string。 这似乎是需要的,但它不是默认设置的一部分。 然而,networkingsearch揭示了一些手动实现的例子 :

 CREATE AGGREGATE textcat_all( basetype = text, sfunc = textcat, stype = text, initcond = '' ); 

这是CREATE AGGREGATE文档。

为了得到在它们之间插入的“,”,而不是最后,你可能想要自己的连接函数,并将其replace为上面的“textcat”。 这里是一个我放在一起,但没有testing( 更新:在8.3.12testing和工作正常):

 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; 

注意:即使行中的值为空/空,上面的函数也会输出一个逗号,输出:

 a, b, c, , e, , g 

如果你想删除额外的逗号输出:

 a, b, c, e, g 

只需添加一个ELSIF检查function:

 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; 

如何使用Postgres内置的数组函数? 至less在8.4这个开箱即用:

 SELECT company_id, array_to_string(array_agg(employee), ',') FROM mytable GROUP BY company_id; 

从PostgreSQL 9.0开始,您可以使用名为string_agg的聚合函数。 你的新SQL应该看起来像这样:

 SELECT company_id, string_agg(employee, ', ') FROM mytable GROUP BY company_id; 

我声称没有信用的答案,因为我发现它后一些search:

我不知道的是PostgreSQL允许你用CREATE AGGREGATE定义你自己的聚合函数

PostgreSQL列表上的这篇文章展示了创build一个函数来执行所需的操作是多么的微不足道:

 CREATE AGGREGATE textcat_all( basetype = text, sfunc = textcat, stype = text, initcond = '' ); SELECT company_id, textcat_all(employee || ', ') FROM mytable GROUP BY company_id; 

如前所述,创build自己的聚合函数是正确的。 这是我的串联聚合函数(你可以在法语中find详细信息 ):

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

);

然后用它作为:

 SELECT company_id, concatenate(employee) AS employees FROM ... 

如果您将升级到8.4,最新的公告列表片段可能是有趣的:

直到8.4出现了一个超级本地的东西,你可以在PostgreSQL文档中添加array_accum()函数来将任何列滚动到一个数组中,然后可以被应用程序代码使用,或者与array_to_string()结合来格式化它作为一个列表:

http://www.postgresql.org/docs/current/static/xaggr.html

我会链接到8.4开发文档,但他们似乎并没有列出这个function呢。

如果有人遇到这种情况,需要为9.0以前的数据库寻找一个兼容的shim,除了ORDER BY子句(这也是9.0中引入的语法扩展)之外,可以在string_agg实现所有的东西。

所以在下面的定义中,这将和9.x Postgres数据库一样:

 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上testing

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

跟随Kev的回答,使用Postgres文档:

首先创build一个元素的数组,然后使用内置的array_to_string函数。

 CREATE AGGREGATE array_accum (anyelement) ( sfunc = array_append, stype = anyarray, initcond = '{}' ); select array_to_string(array_accum(name),'|') from table group by id; 

再次使用string连接的自定义集合函数:您需要记住,select语句将按任意顺序放置行,因此您需要在from语句中使用order by子句进行子select ,以及然后使用group by子句进行外部select以聚合string,从而:

 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 

我发现这个PostgreSQL文档很有帮助: http : //www.postgresql.org/docs/8.0/interactive/functions-conditional.html 。

在我的情况下,我寻求普通的SQL来连接一个字段与括号,如果该字段不是空的。

 select itemid, CASE itemdescription WHEN '' THEN itemname ELSE itemname || ' (' || itemdescription || ')' END from items; 

根据PostgreSQL 9.0及以上版本,您可以使用名为string_agg的聚合函数。 你的新SQL应该看起来像这样:

 SELECT company_id, string_agg(employee, ', ') FROM mytable GROUP BY company_id; 
Interesting Posts