From : http://www.cnblogs.com/lhj588/archive/2012/06/15/2550392.html#

今晚需要统计数据生成简易报表,由原表格数据是单行的形式,最好转换为列表格式,由网上介绍方法实现如下:

希望获得的最终效果见下:

+-------+------+-------+-------+--------+--------+--------+---------------------+---------+
| 房间  | 房租 | 水费  | 电费  | 卫生费 | 电视费 | 网络费 | 记录时间            | total   |
+-------+------+-------+-------+--------+--------+--------+---------------------+---------+
| 0201  |  400 |     0 |     0 |     10 |      0 |      0 | 2011-02-08 11:01:21 |     410 |
| 0204  |  150 |     0 |     0 |     10 |      0 |      0 | 2011-02-08 11:00:21 |     160 |
| 0206  |  150 |     0 |     0 |     10 |      0 |      0 | 2011-01-16 18:02:50 |     160 |
| 0302  |  350 | 40.92 | 18.91 |     20 |     50 |     50 | 2011-01-18 01:45:23 |  529.83 |
| 0306  |  150 |     0 |     0 |     10 |      0 |      0 | 2011-02-08 11:23:15 |     160 |
| 0308  |  200 |     0 |     0 |     10 |      0 |      0 | 2011-03-28 22:26:41 |     210 |
| total | 1400 | 40.92 | 18.91 |     70 |     50 |     50 | 2011-03-28 22:26:41 | 1629.83 |
+-------+------+-------+-------+--------+--------+--------+---------------------+---------+

实现的SQL语句见下:

mysql>  SELECT
    ->      IFNULL(RoomNo,'total') AS 房间,
    ->      SUM(IF(FeeName='房租',FeeMoney,0)) AS 房租,
    ->      SUM(IF(FeeName='水费',FeeMoney,0)) AS 水费,
    ->      SUM(IF(FeeName='电费',FeeMoney,0)) AS 电费,
    ->      SUM(IF(FeeName='卫生费',FeeMoney,0)) AS 卫生费,
    ->      SUM(IF(FeeName='电视费',FeeMoney,0)) AS 电视费,
    ->      SUM(IF(FeeName='网络费',FeeMoney,0)) AS 网络费,
    ->      IFNULL(CDate, CDate) AS 记录时间,
    ->      SUM(IF(FeeName='total',FeeMoney,0)) AS total
    ->  FROM (
    -> select no.RoomNo as RoomNo, IFNULL(f.FeeName, 'total') as FeeName, SUM(f.FeeMoney) as FeeMoney, f.CreateDate as CDate
    -> from roomnoinfo no, Fee f
    -> where no.bid=1 and no.beempty='full' and no.RoomNo=f.RoomNo and
    -> f.CreateDate < '2011-03-31' and f.CreateDate >'2011-01-01'
    -> GROUP BY RoomNO, FeeName
    -> WITH ROLLUP
    -> HAVING RoomNO IS NOT NULL
    ->  ) AS A
    ->  GROUP BY RoomNo
    ->  WITH ROLLUP;

源数据的表格式如下:

mysql> select RoomNo, CreateDate, FeeName, FeeMoney from Fee where bid=1;
+--------+---------------------+---------+----------+
| RoomNo | CreateDate          | FeeName | FeeMoney |
+--------+---------------------+---------+----------+
| 0101   | 2011-01-15 22:41:24 | 房租    |      200 |
| 0101   | 2011-01-15 22:41:24 | 水费    |     13.2 |
| 0101   | 2011-01-15 22:41:24 | 电费    |      6.1 |
| 0102   | 2011-01-16 17:01:52 | 房租    |      150 |
| 0102   | 2011-01-16 17:01:52 | 水费    |    145.2 |
| 0102   | 2011-01-16 17:01:52 | 电费    |     67.1 |
| 0102   | 2011-01-16 17:01:52 | 卫生费  |       10 |
| 0204   | 2011-02-08 11:00:21 | 房租    |      150 |
| 0204   | 2011-02-08 11:00:21 | 水费    |     NULL |
| 0204   | 2011-02-08 11:00:21 | 电费    |     NULL |
| 0204   | 2011-02-08 11:00:21 | 卫生费  |       10 |
| 0206   | 2011-01-16 18:02:50 | 房租    |      150 |
| 0206   | 2011-01-16 18:02:50 | 水费    |     NULL |
| 0206   | 2011-01-16 18:02:50 | 电费    |     NULL |
| 0206   | 2011-01-16 18:02:50 | 卫生费  |       10 |
| 0302   | 2011-01-18 01:42:35 | 房租    |      150 |
| 0302   | 2011-01-18 01:42:35 | 水费    |    40.92 |
| 0302   | 2011-01-18 01:42:35 | 电费    |    18.91 |
| 0302   | 2011-01-18 01:42:35 | 卫生费  |       10 |
| 0302   | 2011-01-18 01:45:23 | 卫生费  |       10 |
| 0302   | 2011-01-18 01:45:23 | 房租    |      200 |
| 0302   | 2011-01-18 01:45:23 | 网络费  |       50 |
| 0302   | 2011-01-18 01:45:23 | 电视费  |       50 |
| 0306   | 2011-02-08 11:23:15 | 房租    |      150 |
| 0306   | 2011-02-08 11:23:15 | 水费    |     NULL |
| 0306   | 2011-02-08 11:23:15 | 电费    |     NULL |
| 0306   | 2011-02-08 11:23:15 | 卫生费  |       10 |
| 0308   | 2011-03-28 22:26:41 | 房租    |      200 |
| 0308   | 2011-03-28 22:26:41 | 水费    |     NULL |
| 0308   | 2011-03-28 22:26:41 | 电费    |     NULL |
| 0308   | 2011-03-28 22:26:41 | 卫生费  |       10 |
+--------+---------------------+---------+----------+
31 rows in set (0.02 sec)

原文介绍地址 http://blogold.chinaunix.net/u3/90603/showart_2017912.html

数据样本:

create table tx(
 id int primary key,
 c1 char(2),
 c2 char(2),
 c3 int
);

insert into tx values
(1 ,'A1','B1',9),
(2 ,'A2','B1',7),
(3 ,'A3','B1',4),
(4 ,'A4','B1',2),
(5 ,'A1','B2',2),
(6 ,'A2','B2',9),
(7 ,'A3','B2',8),
(8 ,'A4','B2',5),
(9 ,'A1','B3',1),
(10 ,'A2','B3',8),
(11 ,'A3','B3',8),
(12 ,'A4','B3',6),
(13 ,'A1','B4',8),
(14 ,'A2','B4',2),
(15 ,'A3','B4',6),
(16 ,'A4','B4',9),
(17 ,'A1','B4',3),
(18 ,'A2','B4',5),
(19 ,'A3','B4',2),
(20 ,'A4','B4',5);

mysql> select * from tx;
+----+------+------+------+
| id | c1   | c2   | c3   |
+----+------+------+------+
|  1 | A1   | B1   |    9 |
|  2 | A2   | B1   |    7 |
|  3 | A3   | B1   |    4 |
|  4 | A4   | B1   |    2 |
|  5 | A1   | B2   |    2 |
|  6 | A2   | B2   |    9 |
|  7 | A3   | B2   |    8 |
|  8 | A4   | B2   |    5 |
|  9 | A1   | B3   |    1 |
| 10 | A2   | B3   |    8 |
| 11 | A3   | B3   |    8 |
| 12 | A4   | B3   |    6 |
| 13 | A1   | B4   |    8 |
| 14 | A2   | B4   |    2 |
| 15 | A3   | B4   |    6 |
| 16 | A4   | B4   |    9 |
| 17 | A1   | B4   |    3 |
| 18 | A2   | B4   |    5 |
| 19 | A3   | B4   |    2 |
| 20 | A4   | B4   |    5 |
+----+------+------+------+
20 rows in set (0.00 sec)

mysql>

期望结果

+------+-----+-----+-----+-----+------+
|C1    |B1   |B2   |B3   |B4   |Total |
+------+-----+-----+-----+-----+------+
|A1    |9    |2    |1    |11   |23    |
|A2    |7    |9    |8    |7    |31    |
|A3    |4    |8    |8    |8    |28    |
|A4    |2    |5    |6    |14   |27    |
|Total |22   |24   |23   |40   |109   |
+------+-----+-----+-----+-----+------+

1. 利用SUM(IF()) 生成列 + WITH ROLLUP 生成汇总行,并利用 IFNULL将汇总行标题显示为 Total

mysql> SELECT
    ->     IFNULL(c1,'total') AS total,
    ->     SUM(IF(c2='B1',c3,0)) AS B1,
    ->     SUM(IF(c2='B2',c3,0)) AS B2,
    ->     SUM(IF(c2='B3',c3,0)) AS B3,
    ->     SUM(IF(c2='B4',c3,0)) AS B4,
    ->     SUM(IF(c2='total',c3,0)) AS total
    -> FROM (
    ->     SELECT c1,IFNULL(c2,'total') AS c2,SUM(c3) AS c3
    ->     FROM tx
    ->     GROUP BY c1,c2
    ->     WITH ROLLUP
    ->     HAVING c1 IS NOT NULL
    -> ) AS A
    -> GROUP BY c1
    -> WITH ROLLUP;
+-------+------+------+------+------+-------+
| total | B1   | B2   | B3   | B4   | total |
+-------+------+------+------+------+-------+
| A1    |    9 |    2 |    1 |   11 |    23 |
| A2    |    7 |    9 |    8 |    7 |    31 |
| A3    |    4 |    8 |    8 |    8 |    28 |
| A4    |    2 |    5 |    6 |   14 |    27 |
| total |   22 |   24 |   23 |   40 |   109 |
+-------+------+------+------+------+-------+
5 rows in set, 1 warning (0.00 sec)

2. 利用SUM(IF()) 生成列 + UNION 生成汇总行,并利用 IFNULL将汇总行标题显示为 Total
mysql> select c1,
    -> sum(if(c2='B1',C3,0)) AS B1,
    -> sum(if(c2='B2',C3,0)) AS B2,
    -> sum(if(c2='B3',C3,0)) AS B3,
    -> sum(if(c2='B4',C3,0)) AS B4,SUM(C3) AS TOTAL
    -> from tx
    -> group by C1
    -> UNION
    -> SELECT 'TOTAL',sum(if(c2='B1',C3,0)) AS B1,
    -> sum(if(c2='B2',C3,0)) AS B2,
    -> sum(if(c2='B3',C3,0)) AS B3,
    -> sum(if(c2='B4',C3,0)) AS B4,SUM(C3) FROM TX
    -> ;
+-------+------+------+------+------+-------+
| c1    | B1   | B2   | B3   | B4   | TOTAL |
+-------+------+------+------+------+-------+
| A1    |    9 |    2 |    1 |   11 |    23 |
| A2    |    7 |    9 |    8 |    7 |    31 |
| A3    |    4 |    8 |    8 |    8 |    28 |
| A4    |    2 |    5 |    6 |   14 |    27 |
| TOTAL |   22 |   24 |   23 |   40 |   109 |
+-------+------+------+------+------+-------+
5 rows in set (0.00 sec)

mysql>

3.  利用SUM(IF()) 生成列,直接生成结果不再利用子查询
mysql> select ifnull(c1,'total'),
    -> sum(if(c2='B1',C3,0)) AS B1,
    -> sum(if(c2='B2',C3,0)) AS B2,
    -> sum(if(c2='B3',C3,0)) AS B3,
    -> sum(if(c2='B4',C3,0)) AS B4,SUM(C3) AS TOTAL
    -> from tx
    -> group by C1 with rollup ;
+--------------------+------+------+------+------+-------+
| ifnull(c1,'total') | B1   | B2   | B3   | B4   | TOTAL |
+--------------------+------+------+------+------+-------+
| A1                 |    9 |    2 |    1 |   11 |    23 |
| A2                 |    7 |    9 |    8 |    7 |    31 |
| A3                 |    4 |    8 |    8 |    8 |    28 |
| A4                 |    2 |    5 |    6 |   14 |    27 |
| total              |   22 |   24 |   23 |   40 |   109 |
+--------------------+------+------+------+------+-------+
5 rows in set (0.00 sec)

mysql>

4. 动态,适用于列不确定情况,

mysql> SET @EE='';
mysql> SELECT @EE:=CONCAT(@EE,'SUM(IF(C2=\'',C2,'\'',',C3,0)) AS ',C2,',') FROM (SELECT DISTINCT C2 FROM TX) A;

mysql> SET @QQ=CONCAT('SELECT ifnull(c1,\'total\'),',LEFT(@EE,LENGTH(@EE)-1),' ,SUM(C3) AS TOTAL FROM TX GROUP BY C1 WITH ROLLUP');
Query OK, 0 rows affected (0.00 sec)

mysql> PREPARE stmt2 FROM @QQ;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> EXECUTE stmt2;
+--------------------+------+------+------+------+-------+
| ifnull(c1,'total') | B1   | B2   | B3   | B4   | TOTAL |
+--------------------+------+------+------+------+-------+
| A1                 |    9 |    2 |    1 |   11 |    23 |
| A2                 |    7 |    9 |    8 |    7 |    31 |
| A3                 |    4 |    8 |    8 |    8 |    28 |
| A4                 |    2 |    5 |    6 |   14 |    27 |
| total              |   22 |   24 |   23 |   40 |   109 |
+--------------------+------+------+------+------+-------+
5 rows in set (0.00 sec)

mysql>

以上均由网友  liangCK , wwwwb , WWWWA , dap570 提供, 再次感谢他们的支持。

其实数据库中也可以用 CASE WHEN / DECODE 代替 IF

【转】Mysql行转换为列的更多相关文章

  1. MYSQL 行转列 以及基本的聚合函数count,与group by 以及distinct组合使用

    在统计查询中,经常会用到count函数,这里是基础的 MYSQL 行转列 以及基本的聚合函数count,与group by 以及distinct组合使用 -- 创建表 CREATE TABLE `tb ...

  2. excel中怎么将行转换为列及列转换成行

    操作方法 01 选中要把行转换为列的数据.然后点击键盘上的ctrl+c. 02 在需要放置的单元格上,右键点击,然后点击菜单上的‘选择性粘贴’. 03 在弹出的窗口上,点击勾选上‘转置’.点击确定按钮 ...

  3. MySQL 行转列 -》动态行转列 -》动态行转列带计算

    Pivot Table Using MySQL - A Complete Guide | WebDevZoomhttp://webdevzoom.com/pivot-table-using-mysql ...

  4. MySql 行转列 存储过程实现

    同学们在使用mysql的过程中,会遇到一个行转列的问题,就是把多条数据转化成一条数据 用多列显示. 方法1. 实现方式用下面的存储过程,表名对应的修改就行. BEGIN declare current ...

  5. mysql行转列,函数GROUP_CONCAT(expr)

    demo: 语句: SELECT '行' id, '' product_nameUNIONSELECT id, product_name FROM `product` WHERE id < 5 ...

  6. mysql行转列 问题 SUM(IF(条件,列值,0))

    sum(if(条件,列值,0))语法用例: select name,sum(if(subject="语文",score,0)) as "语文" from gra ...

  7. mysql行转列、列转行示例

    最近在开发过程中遇到问题,需要将数据库中一张表信息进行行转列操作,再将每列(即每个字段)作为与其他表进行联表查询的字段进行显示. 借此机会,在网上查阅了相关方法,现总结出一种比较简单易懂的方法备用. ...

  8. MySQL行转列、列转行

    一.行转列 有如图所示的表,现在希望查询的结果将行转成列 建表语句如下: CREATE TABLE `TEST_TB_GRADE` ( `ID` int(10) NOT NULL AUTO_INCRE ...

  9. mysql 行转列 列转行

    一.行转列 即将原本同一列下多行的不同内容作为多个字段,输出对应内容. 建表语句 DROP TABLE IF EXISTS tb_score; CREATE TABLE tb_score( id ) ...

随机推荐

  1. R语言编程艺术(3)R语言编程基础

    本文对应<R语言编程艺术> 第7章:R语言编程结构: 第9章:面向对象的编程: 第13章:调试 ============================================== ...

  2. React Native Android启动白屏的一种解决方案下

    实现思路 思路大流程: 1.APP启动的时候控制ReactActivity从而显示启动屏. 2.编写原生模块,提供一个关闭启动屏的公共接口. 3.在js的适当位置(一般是程序初始化工作完成后)调用上述 ...

  3. Mysql Lock wait timeout exceeded; try restarting transaction的问题

    今天在后台跑任务的时候,发现了数据库报错1205 - Lock wait timeout exceeded; try restarting transaction.问题原因是因为表的事务锁,以下是解决 ...

  4. 子类 父类强转 HttpServlet service实现

    相当于 走父类 临时走了一趟 HttpServletRequest ->ServletRequets -> HttpServeltRequest /* */ public void ser ...

  5. 领英Linkedin信息搜集工具InSpy

    领英Linkedin信息搜集工具InSpy   领英Linkedin是一个知名职业社交媒体网站.通过该网站,渗透测试人员可以获取公司内部组成和员工信息.Kali Linux提供一款专用的信息收集工具I ...

  6. hdu 1241Oil Deposits(dfs模板)

    题目链接—— http://acm.hdu.edu.cn/showproblem.php?pid=1241 首先给出一个n*m的字符矩阵,‘*’表示空地,‘@’表示油井.问在这个矩阵中有多少组油井区? ...

  7. 概率dp总结

    终于做到概率dp题了,开个总结帖记录一下 首先是几篇论文:有关概率和期望问题的研究 做了这么多题,实际上没什么特别好总结的,就是搞清状态和转移,顺着写就行了,和基本dp差不多 概率是由过去到现在dp[ ...

  8. maven执行update命令时报org/apache/maven/shared/filtering/MavenFilteringException错误

    原 maven执行update命令时报org/apache/maven/shared/filtering/MavenFilteringException错误 在eclipse中对准项目执行maven- ...

  9. NOIP 2013 转圈游戏

    [题目描述] n个小伙伴(编号从 0 到 n−1)围坐一圈玩游戏.按照顺时针方向给 n 个位置编号,从 0 到 n−1.最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……, ...

  10. CentOS下KVM增加磁盘/磁盘扩容/在线扩容

    一.磁盘镜像操作(适用于raw和qcow2格式) 1.创建镜像 qemu-img create -f qcow2(格式) /kvm/centos1_1.qcow2(路径) 5G(容量) 2.修改镜像容 ...