我正在寻找一种经过查询来链接一个组内字段字符串的方法。 例如,我有一张桌子: 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;