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. PHP与MySQL设计模式:代理模式

    一.数据库连接通用类 重要的接口: 接口用来存储MySQL连接数据.实现这个接口的类都可以使用这些数据. 通过接口可以隔离出程序中一个简单而必要的部分,任何程序都可以实现这个接口. 接口通过inter ...

  2. Java动态代理机制研读

    java动态加载类(反射机制) /*MyClass.java*/ public class MyClass { public int id; public String name; public in ...

  3. Linux下部署tomcat及tomcat war包应用程序

    1, 通过winscp将tomcat包(6和7版本都是一样的安装方法)和jdk-6u27-linux-x64.bin安装文件传送到linux 系统/opt里面.(这里没有固定要传送到/opt/hn,可 ...

  4. Prettier来统一代码风格

    prettier是一款解决代码风格问题的代码格式化工具,功能强大,简单易用,支持多语言,减少配置项. 前端开发过程中每个人写JavaScript的代码风格都不一样,又不能说别人写的代码有问题,这都是习 ...

  5. 深入分析Spring Boot2,解决 java.lang.ArrayStoreException异常

    将某个项目从Spring Boot1升级Spring Boot2之后出现如下报错,查了很多不同的解决方法都没有解决: Spring boot2项目启动时遇到了异常: java.lang.ArraySt ...

  6. .NET工作准备--04ASP.NET

    (已过时) ASP.NET 1.开发基础 *asp.net以什么形式运行?.net宿主的概念,ISAPI的概念,ASP.NET基本运行机制; .net宿主的概念:CLR被实现为一个标准的COM服务器组 ...

  7. html (第四本书第六章盒子模型参考)

    上机1 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8 ...

  8. C# EF Attach 与 Entry

    先了解一下 EF 框架的 EntityState 在使用EF框架时, 我们通常都是通过调用 SaveChanges() 方法把增加/修改/删除的数据提交到数据库,但是上下文是如何知道实体对象是增加.修 ...

  9. Develop with asyncio部分的翻译

    Develop with asyncio 异步程序和普通的连续程序(也就是同步程序)是很不一样的,这里会列出一些常见的陷阱,并介绍如何去避开他们. Debug mode of asyncio 我们用a ...

  10. 洛谷P1133 教主的花园

    题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树 ...