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

  • 相关阅读:
    扩展当easyui datagrid无数据时,显示特定值。如:没有数据
    draggable datagrid columns
    easyui combobox 带 checkbox
    LightOJ1003---Drunk(拓扑排序判环)
    算法分析---回文数推断
    Android集成百度地图SDK
    BS一机双屏的解决方式
    myeclipse中更改web项目在tomcat中部署的路径
    Linux内核调试技术——jprobe使用与实现
    【Servlet】把文件写到Respond输出流里面供用户下载
  • 原文地址:https://www.cnblogs.com/lhj588/p/2550392.html
Copyright © 2011-2022 走看看