可以看到我们做的事情很简单,就是将聚合的数据放到一个数组里,当然也可以用一种更简便的写法来完成,即数组操作符 ||,它可以直接将元素put到数组里。
准备ffunc完成了第一步之后,回归主题,我们要实现的是多行数据合并成一列,那么很简单,上面我们用过了array_to_string这个数组函数,这里我们同样利用这个思路,将我们准备好的数组通过指定的分隔符转换成字符串。下面是ffunc的代码:
CREATE FUNCTION "public"."NewProc"(aa _text) RETURNS "pg_catalog"."text" AS $BODY$ BEGIN RETURN array_to_string(aa, '<br />'); END; $BODY$ LANGUAGE 'plpgsql' VOLATILE COST 100 ; ALTER FUNCTION "public"."NewProc"(aa _text) OWNER TO "postgres";很简单,通过br分隔符将参数数组转换成字符串并返回。
CREATE AGGREGATE上面的两个自定义函数都准备好之后,我们就可以创建我们自定义的聚合函数了,参考上面图(3)的语法,写出创建语句:
CREATE AGGREGATE ToOneRow(TEXT) ( SFUNC = SFUNC_ToOneRow, STYPE = TEXT[], FINALFUNC = FFUNC_ToOneRow );这样我们就创建完成了,赶紧尝试运行一下是否可以使用:
select ToOneRow(behavior_code) as behavior_code,factor_code from t_evaluation_behavior group by factor_code order by factor_code;Congratulation!运行如上的SQL语句,依旧可以正确的得到和图(2)一模一样的结果。
最佳实践(Best Practice)如果是在8.x的版本中仅仅只能通过上述的方式解决问题了,但自从postgres 9之后,又新增了一批内置的聚合函数,其中就包含我们上面实现的那种方式,所以9.x的版本也就不需要我们再去自己创建了!下面看一下官方文档中提供的9.3版本的内置聚合函数表:
注意一下我用红色标记出来的这个函数,是否有种豁然开朗的感觉呢?这里不得不再次赞叹一下postgres确实很强大!赶紧测试一下是否有效:
select string_agg(behavior_code,'<br />') as behavior_code,factor_code from t_evaluation_behavior group by factor_code order by factor_code;Perfect!和图(2)一模一样!第一个参数是需要聚合的列名,第二个参数是分隔符,这样就更加方便的完成了我们的需求~
总结简单记录一下这种需求,以及postgres中自定义聚合函数的方法。如有错误的地方欢迎批评指正,The End。
------------------------------------华丽丽的分割线------------------------------------
在CentOS 6.5上编译安装PostgreSQL 9.3数据库
CentOS 6.3环境下yum安装PostgreSQL 9.3
Ubuntu下LAPP(Linux+Apache+PostgreSQL+PHP)环境的配置与安装
PostgreSQL配置Streaming Replication集群
------------------------------------华丽丽的分割线------------------------------------