转自http://csk83.sinaapp.com/?p=104

在实际应用中常常遇见这样的情况,见下表,我们现在需要统计出来每年每个人的工资总和以及发放月份。

user_name year month money
张三 2011 1 900
张三 2011 2 1200
张三 2011 5 1100
张三 2011 6 1300
李四 2011 1 1100
李四 2011 3 1200

即我们要得到下面表的结果

user_name year monthes total money
张三 2011 1,2,5,6 4500
李四 2011 1,3 2300

首先我们想到的是有这样的SQL语句:
SELECT user_name,year,myfunction(month) AS monthes, SUM(money) AS total_money FROM table GROUP BY user_name,year;

像count或者sum一样吧数据表中的某个字段按照需要拼接起来,但是在PostgreSQL好像没有直接的方法来实现(或许有笔者没有发现,正因为没有发现所以笔者才研究了半天得到下面的心得)。

方法一:在PostgreSQL中如果不自定义函数直接用SQL来实现

SELECT t1.user_name, t1.year, ARRAY_TO_STRING(array(SELECT t2.month FROM table t2 WHERE t2.user_name=t1.user_name AND  t2.year=t1.year), ‘,’)  AS monthes, SUM(t1.money) AS total_money FROM table t1 WHERE 1 GROUP BY t1.user_name, t1.year;

这里主要是用了PostgreSQL的内置数组函数array_to_string把数组拼接成字符串。

方法二:自己写一个聚合函数csk_test来实现

结合上面array_to_sting的用法,根据聚合函数定义方法研究出用聚合函数来实现的方法:

– 1 开启plpgsql的支持,如果没有需要运行下面两行SQL开启plpgsql支持
CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler AS ‘$libdir/plpgsql’ LANGUAGE C;
CREATE TRUSTED LANGUAGE plpgsql HANDLER “plpgsql_call_handler”;
– 2 创建函数
—- 2.1 收集数据到一个数组
CREATE FUNCTION csk_test_start(a TEXT[], s TEXT) RETURNS TEXT[] AS $$
BEGIN
RETURN a || s;
END;
$$ LANGUAGE plpgsql;
—- 2.2 最后处理函数,把数组转换成字符串输出
CREATE FUNCTION csk_test_final(a TEXT[]) RETURNS TEXT AS $$
BEGIN
RETURN array_to_string(a, ‘,’);
END;
$$ LANGUAGE plpgsql;
– 3 创建聚集函数
CREATE AGGREGATE csk_test(
BASETYPE = TEXT,
SFUNC = csk_test_start,
STYPE = TEXT[],
FINALFUNC = csk_test_final
);

现在我们再次用本文开始的SQL就可以实现我们的要求了
SELECT user_name,year,csk_test(CAST(month to varchar)) AS monthes, SUM(money) AS total_money FROM table GROUP BY user_name,year;

需要注意的是,上面的聚集函数接收的数据类型是text,所以在用的时候month整型转换成了varchar类型,当然也可以直接修改上面的代码让它们的类型一致。聚合函数在文本字段的处理上在PostgreSQL 8.4上测试通过了,至于数字类型其他类型转换后是否能行没有测试过。

方法二是通过聚合函数引用自定义函数来实现的,其实还可以直接调用系统函数array_append来实现:

CREATE AGGREGATE csk_test(
basetype = integer,
sfunc = array_append,
stype = integer[],
initcond = ‘{}’
);

可参考http://www.postgresql.org/docs/9.1/static/functions-array.html

[Postgres]合并多行到一列(转)的更多相关文章

  1. SQL SERVER 字符合并多行为一列

    [字符合并多行为一列] 思路1:行转列,在与字符拼接(适用每组列数名相同) 思路2:转xml,去掉多余字符(适用所有) 假设兴趣表Hobbys Name Hobby 小张 打篮球 小张 踢足球 Nam ...

  2. poi导出excel合并单元格(包括列合并、行合并)

    1 工程所需jar包如下:commons-codec-1.5.jarcommons-logging-1.1.jarlog4j-1.2.13.jarjunit-3.8.1.jarpoi-3.9-2012 ...

  3. DataGridView合并单元格(一列或一行)

    #region"合并单元格的测试(一列或一行)" // int?是搜索一种类型(可空类型),普通的int不能为null,而用int?,其值可以为null //private int ...

  4. Java导出Excel表,POI 实现合并单元格以及列自适应宽度(转载)

    POI是apache提供的一个读写Excel文档的开源组件,在操作excel时常要合并单元格,合并单元格的方法是: sheet.addMergedRegion(new CellRangeAddress ...

  5. POI 实现合并单元格以及列自适应宽度

    POI是apache提供的一个读写Excel文档的开源组件,在操作excel时常要合并单元格,合并单元格的方法是: sheet.addMergedRegion(new CellRangeAddress ...

  6. 使用element-ui 组件动态合并table的行/列(第二次修改)

    这是第二次修改,在通过调用后台接口返回来的时候,发现了代码中的问题:现在将博客中错误的地方改过来,添加备注 文章需求:动态实现table表格中行/列的自动合并 使用框架及UI类库:Vue+Elemen ...

  7. EasyUi 合并单元格占列显示

    $("#TableContainer").datagrid({                url: '',                method: "get&q ...

  8. sql查询 ,多行数据合并成一行,并且显示合并后某一列的值拼接结果

    select  [value] = stuff((select ','+modmb003  from modmb detail where modmb=18 for xml path('')), 1, ...

  9. postgres serial创建自增列

    Sequence是数据库中一类特殊的对象,其用于生成唯一数字标识符.一个典型的应用场景就是手动生成一系列主键.Sequence和MySQL中的AUTO_INCREMENT的概念很像. 创建序列Sequ ...

随机推荐

  1. CentOS7.6安装Redis

    官网下载地址:https://redis.io/download 第一步:软件下载安装 进行安装目录:cd /opt/software (如果目录不存在,请先创建目录) 下载二进制包:wget htt ...

  2. TCP粘包拆包场景

    TCP编程底层都有粘包和拆包机制,因为我们在C/S这种传输模型下,以TCP协议传输的时候,在网络中的byte其实就像是河水,TCP就像一个搬运工,将这流水从一端转送到另一端,这时又分两种情况: 1)如 ...

  3. Delphi IOS class_addMethod

    class_addMethod 学习FMX.Platform.iOS.pas文件的处理办法 d:\program files (x86)\embarcadero\studio\17.0\source\ ...

  4. 关于LOH(Large Object Heap)及内存泄漏

    关于LOH(Large Object Heap)的. .NET CLR中对于大于85000字节的内存既不像引用类型那样分配到普通堆上,也不像值类型那样分配到栈上,而是分配到了一个特殊的称为LOH的内部 ...

  5. Kafka Zookeeper 基本命令示例

    Kafka 新建Topic bin/kafka-topics. --replication-factor --partitions --topic my-topic 查看已存在Topic列表 bin/ ...

  6. Android中的网络编程

    谷歌在Android6.0之后就废弃了使用HttpClinet进行网络连接.所以,这里需要重点学习的是通过HttpUrlConnect进行网络连接. String path="这里是你想要的 ...

  7. 通过args数组获取数据

    ----------siwuxie095                     通过 main 方法的 args数组 可以从控制台获取一组字符串数据     如:     package com.s ...

  8. shell if,case,for,while语法

    #shell if的语法 if [空格 xxx 空格] then echo xxxxx exit 1/2/3/4/.... 0表示正确. elif [空格 xxx 空格] then echo xxxx ...

  9. SpringBoot30 整合Mybatis-Plus、整合Redis、利用Ehcache实现二级缓存、利用SpringCache和Redis作为缓存

    1 环境说明 JDK: 1.8 MAVEN: 3. SpringBoot: 2.0.4 2 SpringBoot集成Mybatis-Plus 2.1 创建SpringBoot 利用IDEA创建Spri ...

  10. svn: Can't connect to host

    关于“svn: Can't connect to host '*.*.*.*': 由于连接方在一段时间后没有正确答复或连接”的解决方法   阿里云服务器环境(PHP+Nginx+MySQL) [原因1 ...