- 创建一个聚集函数:
CREATE AGGREGATE int_array_accum ( BASETYPE=_int4, SFUNC=intarray_push_array, stype=_int4);
这个聚集函数的目的很简单,就是把两个整数数组拼接起来,返回之。具体的文档,可以参考:
http://www.pgsqldb.org/pgsqldoc-8.1c/xaggr.html http://www.pgsqldb.org/pgsqldoc-8.1c/sql-createaggregate.html
和 intarray 的文档:
http://www.pgsqldb.org/mwiki/index.php/Intarray
以及 intagg 模块的文档:
http://www.pgsqldb.org/mwiki/index.php/Intagg
其中用到的拼接函数 intarray_push_array 其实是 intarray 的两个数组相加(+号)的处理函数。可以在intarray的初始化SQL文件 _int.sql 里面找到(在4E的RPM包里是/usr/local/pgsql/share/contrib/_int.sql),
- 执行下面的查询:
select * from tellers where ( select int_array_accum(a.array) from (select subarray(int_array_aggregate(tid),0,5) as array from tellers group by bid) a) @@ tid::text::query_int;
就会得到期望的输出。这个查询有点意思,我们分解看看:
最内层的:
select subarray(int_array_aggregate(tid),0,5) as array from tellers group by bid;
我们其实是对每个 bid (连锁店ID),然后调用 int_array_aggregate 聚集函数(见intagg)的文档,把每个 bid 输出的 tid 组合成一个整数数组,int_array_aggregate是intagg模块提供的一个聚集函数,因为group by之后,在SELECT的输出列表里只能出现group by的id和聚集函数,所以这里必须聚集一下。之后用 intarray的subarray取输出的头5个元素。
然后,将上面这个查询的输出,再次用聚集函数拼成一个更大的数组:
select int_array_accum(a.array) from (select subarray(int_array_aggregate(tid),0,5) as array from tellers group by bid) a;
因为聚集函数不能嵌套,所以我们用一个子查询骗骗它。然后就得到一个N长的整数数组,里头的所有 ID就是我们需要取出来的ID,于是,最后:
select * from tellers where ( select int_array_accum(a.array) from (select subarray(int_array_aggregate(tid),0,5) as array from tellers group by bid) a) @@ tid::text::query_int;
把所有在这个数组里头的ID行的对应数据都找出来,我们这里用了intarray 的 @@操作符和query_int类型,不过这个其实也可以用ANY和IN等构造,理论上不复杂,大家都可以试试。
