博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【转】Mysql行转换为列
阅读量:7121 次
发布时间:2019-06-28

本文共 7822 字,大约阅读时间需要 26 分钟。

From : 

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

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

+-------+------+-------+-------+--------+--------+--------+---------------------+---------+

| 房间  | 房租 | 水费  | 电费  | 卫生费 | 电视费 | 网络费 | 记录时间            | 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)

 

原文介绍地址 

 

数据样本:

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

 

转载地址:http://cvxel.baihongyu.com/

你可能感兴趣的文章
python magic method
查看>>
xml和对象的相互转化
查看>>
计算机启动过程
查看>>
关于改进工作效率
查看>>
list 去重
查看>>
thread-safe
查看>>
spring框架
查看>>
powerdesigner16链接mysql5
查看>>
sqoop 整库导入数据mysql->hive
查看>>
Docker+OpenvSwitch走进VxLAN的世界
查看>>
基于Debian的SteamOS 2.154稳定版发布
查看>>
loader学习小计
查看>>
Vue2.0 新手完全填坑攻略——从环境搭建到发布
查看>>
springboot2.0 常见问题找不到dao
查看>>
系统测试报告 模板
查看>>
gzip,bzip2,xz压缩工具
查看>>
移动互联网、物联网、大数据、人工智能加持的智能家居要如何改进安全?
查看>>
新的一年,新的精彩,2018你有啥计划?未完成别审核
查看>>
[交流乐园]开发者论坛一周精粹(第五十二期) 阿里云备案最全流程指导
查看>>
java springmvc+springboot+mybatis+restful b2b2c电子商城
查看>>