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. jQuery的类数组对象结构(转)

    原文:http://www.imooc.com/code/3248 为什么是类数组对象呢? 很多人迷惑的jQuery为什么能像数组一样操作,通过对象get方法或者直接通过下标0索引就能转成DOM对象. ...

  2. 010.MySQL-Keepalived搭配脚本04

    vim /etc/keepalived/check_MySQL.sh #!/bin/bash pkill keepalived

  3. centos7 静默安装oracle

    系统centos7.4 mini 关闭selinux.firewalld 配置主机名: hostnamectl set-hostname  --static oracle 之前说oracle不认cen ...

  4. 懒人的福利?教你用set维护斜率优化凸包

    斜率优化题目大家肯定都做得不少了,有一些题目查询插入点的x坐标和查询斜率都不单调,这样就需要维护动态凸包并二分斜率.(例如bzoj1492) 常规的做法是cdq分治或手写平衡树维护凸包,然而如果我不愿 ...

  5. Lvs+Keepalived+Mysql

    环境 [root@node1 ~]# cat /etc/redhat-release CentOS Linux release (Core) [root@node1 ~]# uname -a Linu ...

  6. Eclipse中执行Maven命令时控制台输出乱码

    Maven 默认编码为 GBK: 在 Eclipse 控制台输出乱码: 解决方法:将以下代码添加到 pom.xml 的 <project> 节点下: <project> …… ...

  7. MikroTik RouterOS网址资源收集

    routeros|mikrotik|ros|软路由论坛|中国路由网|软件路由|软件路由器|routeros技术论坛|路由论坛 - Powered by Discuz!   Mikrotik RB450 ...

  8. JAVA泛型中的有界类型(extends super)(转)

    JDK1.5中引入了泛型(Generic)机制.泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Ja ...

  9. HDU 4122 Alice's mooncake shop (RMQ)

    Alice's mooncake shop Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  10. css的浮动

    浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止. 由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样. 一 css的浮动 CSS提供了元素对 ...