mysql行列转换方法总结


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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>

期望结果

1
2
3
4
5
6
7
8
9
+------+-----+-----+-----+-----+------+
|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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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()) 生成列,直接生成结果不再利用子查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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. 动态,适用于列不确定情况,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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>

其实数据库中也可以用 CASE WHEN / DECODE 代替 IF

sum(if(c2='B1',C3,0)) AS B1

可改写为

sum(case c2 when 'B1' then C3 else 0 end) AS B1

原文地址:http://blog.chinaunix.net/u3/90603/showart_2017912.html

 

MySQL行列转换实例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
create table student
(
     s_name varchar (20),
     s_subject varchar (20),
     s_point int
);
 
insert into student values ( '张三' , '数学' ,86);
insert into student values ( '李四' , '数学' ,78);
insert into student values ( '张三' , '语文' ,67);
insert into student values ( '张三' , '英语' ,90);
insert into student values ( '李四' , '英语' ,88);
insert into student values ( '李四' , '语文' ,70);
insert into student values ( '王五' , '英语' ,90);
insert into student values ( '王五' , '数学' ,88);
insert into student values ( '王五' , '语文' ,70);
 
select * from student;

方法一:

1
2
3
4
5
6
7
8
9
10
11
select n.s_name as '姓名' ,n.shuxue as '数学' ,n.yuwen as '语文' ,n.yingyu as '英语' ,n.pingjun as '平均成绩' ,n.allcount as '总分' from
(
     select s_name as s_name,
     ( select s_point from student where s.s_name=s_name and s_subject= '数学' ) as shuxue,
     ( select s_point from student where s.s_name=s_name and s_subject= '语文' ) as yuwen,
     ( select s_point from student where s.s_name=s_name and s_subject= '英语' ) as yingyu,
     avg (s_point) as pingjun,
     sum (s_point) as allcount
     from student s group by s_name
 
)n order by allcount desc

结果一:

1
2
3
4
5
6
7
8
+--------+--------+--------+--------+--------------+--------+
| 姓名   | 数学   | 语文   | 英语   | 平均成绩     | 总分   |
+--------+--------+--------+--------+--------------+--------+
| 王五   |     88 |     70 |     90 |      82.6667 |    248 |
| 张三   |     86 |     67 |     90 |      81.0000 |    243 |
| 李四   |     78 |     70 |     88 |      78.6667 |    236 |
+--------+--------+--------+--------+--------------+--------+
3 rows in set (0.00 sec)

方法二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT
     s_name,
     MAX (shuxue) AS 数学,
     MAX (yuwen) AS 语文,
     MAX (yingyu) AS 英语
FROM
(
     SELECT
         s_name,
         CASE s_subject WHEN '数学' THEN s_point END AS shuxue,
         CASE s_subject WHEN '语文' THEN s_point END AS yuwen,
         CASE s_subject WHEN '英语' THEN s_point END AS yingyu
     FROM student
) AS a GROUP BY s_name

结果二:

1
2
3
4
5
6
7
8
+--------+--------+--------+--------+
| s_name | 数学   | 语文   | 英语   |
+--------+--------+--------+--------+
| 张三   |     86 |     67 |     90 |
| 李四   |     78 |     70 |     88 |
| 王五   |     88 |     70 |     90 |
+--------+--------+--------+--------+
3 rows in set (0.00 sec)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值