postgresql 9.3 自定义聚合函数实现多行数据合并成一列
前言常见的一种需求,如下图(1): postgres 8.x的解决方案没错,同标题一样,在postgres 8.x的版本中有几种解决办法,可以通过内置的数组函数 array_to_string通过嵌套子查询的方式来完成,缺点是写法是略微麻烦,而且SQL层次不清晰,效率也不高,下面看一下SQL: select array_to_string (array(select behavior_code from t_evaluation_behavior t2 where t1.factor_code = t2.factor_code),'<br />') as behavior_code,factor_code from t_evaluation_behavior t1 group by factor_code order by factor_code;
运行效果如图(2)一致,接下来再看一下第二种解决方案,通过自定义function结合自定义聚合函数来实现。 创建自定义聚合函数(CREATE AGGREGATE)这种方式使用简便,就是第一次写起来略微麻烦一点。思路和上一种一致,同样是间接的利用了 OK,看完了所有的参数介绍,我们现在实现自己的聚合函数。 准备sfunc这是第一步,sfunc需要我们自定义一个function,根据官方文档的描述,sfunc是一个状态转换函数,下面看一下文档中的这一段话:
OK,根据官方文档的描述需要两个参数,一个是internal-state,一个是next-data-values。下面是sfunc的代码: CREATE FUNCTION "public"."NewProc"(aa _text,s text) RETURNS "pg_catalog"."_text" AS $BODY$ BEGIN RETURN array_append(aa,s);
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE COST 100
;
ALTER FUNCTION "public"."NewProc"(aa _text,s text) OWNER TO "postgres";
可以看到我们做的事情很简单,就是将聚合的数据放到一个数组里,当然也可以用一种更简便的写法来完成,即数组操作符 ||,它可以直接将元素put到数组里。 准备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,factor_code from t_evaluation_behavior group by factor_code order by factor_code;
Perfect!和图(2)一模一样!第一个参数是需要聚合的列名,第二个参数是分隔符,这样就更加方便的完成了我们的需求~ 总结简单记录一下这种需求,以及postgres中自定义聚合函数的方法。如有错误的地方欢迎批评指正,The End。 参考资料:http://www.postgresql.org/docs/9.3/interactive/functions-aggregate.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |