zoukankan      html  css  js  c++  java
  • Mysql行转换为列

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

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

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

  • 相关阅读:
    强化学习的基本迭代方法
    基于文本描述的事务聚类
    学习强化学习之前需要掌握的3种技能
    其它 华硕 ASAU S4100U 系统安装 win10安装 重装系统 Invalid Partition Table 解决
    数据分析 一些基本的知识
    Python 取样式的内容 合并多个文件的样式 自定义样式
    电商 Python 生成补单公司需要的评论格式3
    SpringBlade 本地图片上传 生成缩略图
    SQL Server 字符串截取
    SpringBlade 本地图片上传
  • 原文地址:https://www.cnblogs.com/lhj588/p/2550392.html
Copyright © 2011-2022 走看看