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

  • 相关阅读:
    JS 变量的作用域
    清理网站缓存的几种方法
    C# 将程序添加到启动项 (写入注册表),及从启动项中删除
    EasyUI iconCls
    JQuery Easy Ui dataGrid 数据表格
    datatable转换为json
    Web window.print() 打印
    用js使得输入框input只能输入数字
    隐藏或删除指定的html元素
    使用Asponse.Cell解决Excel科学计数法问题
  • 原文地址:https://www.cnblogs.com/lhj588/p/2550392.html
Copyright © 2011-2022 走看看