这是一道行转列并且构造交叉表的问题:

http://topic.csdn.net/u/20090530/23/0b782674-4b0b-4cf5-bc1a-e8914aaee5ab.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>

期望结果

+------+-----+-----+-----+-----+------+
|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   |
+------+-----+-----+-----+-----+------+

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>

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

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

可改写为

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

mysql行列转换方法总结的更多相关文章

  1. 【转载】mysql行列转换方法总结

    [转载]mysql行列转换方法总结 [MySQL] 行列转换变化各种方法实现总结(行变列报表统计.列变行数据记录统计等) Mysql 列转行统计查询 .行转列统计查询 在某些数据库中有交叉表,但在My ...

  2. 【转】mysql行列转换方法总结

    转:http://blog.chinaunix.net/uid-7692530-id-2567582.html 在某些数据库中有交叉表,但在MySQL中却没有这个功能,但网上看到有不少朋友想找出一个解 ...

  3. mysql 行列动态转换(列联表,交叉表)

    mysql 行列动态转换(列联表,交叉表) (1)动态,适用于列不确定情况 create table table_name( id int primary key, col1 char(2), col ...

  4. MySQL行列转换

    分类: Mysql/postgreSQL 在某些数据库中有交叉表,但在MySQL中却没有这个功能,但网上看到有不少朋友想找出一个解决方法,特发贴集思广义.http://topic.csdn.net/u ...

  5. 【学亮IT手记】MySql行列转换案例

    create table score( name ), math int, english int ); ,); ,); ,); ,); SHOW tables; SELECT * from scor ...

  6. MySQL行列转换拼接

    mysql> select TBL_ID,CREATE_TIME,LAST_ACCESS_TIME,TBL_NAME,TBL_TYPE from TBLS; +--------+-------- ...

  7. mysql行列互相转换

    列转行: mysql> select * from test; +------+----------+-------+ | id | subject | score | +------+---- ...

  8. MySQL 行列相互转换

    行列相互转换 /*创建表*/ CREATE TABLE ic ( NAME ), Product ), amount INT ); INSERT INTO ic VALUES (), (), (), ...

  9. Mysql 行列转换

    一.第一种 原数据表 转换后 DROP TABLE IF EXISTS tempdynamic; CREATE TEMPORARY TABLE tempdynamic ( SELECT p.fsPay ...

随机推荐

  1. JavaWeb从0开始学(二)-----JSP基本语法与编译指令

    在上一节中我们学习了如何搭建一个简单的Web应用,并且已经知晓了一个JSP页面主要由静态的HTML内容和动态的Java脚本共同组成.JSP的基本语法共有JSP注释.JSP声明.输出JSP表达式与JSP ...

  2. Linux MTD子系统 _从模型分析到Flash驱动模板

    MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框架中的设备驱动层,可以说,MTD就是针对Flash设备设计的标准化 ...

  3. 利用shell实现批量添加用户

    批量添加用户并设置随机密码,把添加的用户的名字和密码保存到文件中. [root@lamp scripts]# cat user.sh #!/bin/sh ` do pass=$(-) //取随机数的方 ...

  4. CentOS6.5下安装oracle11gR2

    安装前须知 内存(RAM)的最小要求是 1GB,建议 2GB 及以上. 虚拟内存 swap 建议:内存为 1GB~2GB 时建议swap大小为内存大小的 1.5 倍:内存为 2GB~16GB 时建议s ...

  5. Windows 10 系统Microsoft Edge的使用手册

    Windows 10 默认浏览器(Edge)使用手册 体验网络有了一种新的方法.只有在 Windows 10 上才能找到它. 下面详细介绍一下Edge浏览器的使用规范: 一.打开Windows10系统 ...

  6. POJ2352Stars【树状数组】

    Stars Description Astronomers often examine star maps where stars are represented by points on a pla ...

  7. vagrant up 失败解决办法

    前几天在自己电脑搭建vagrant环境报错:"There was an error while executing `VBoxManage`, a CLI used by Vagrant f ...

  8. 五分钟秒懂Java日志组件

    Java中有许多种日志记录方式,有些API有占位符,有些API没占位符,初学的人可能会搞不清楚这些日志组件的由来.我一开始的时候也是很懵逼的,后来一点点弄懂了于是就又了这篇文章. 在Java中进行日志 ...

  9. (iOS)开发中收集的小方法

    1.颜色转变成图片 - (UIImage *)createImageWithColor:(UIColor *)color {     CGRect rect = CGRectMake(0.0f, 0. ...

  10. JavaScript基础学习(五)—其他引用类型

         JavaScript定义了两个内置对象: Global和Math. 一.Global对象 1.URI编码方法      Global对象的encodeURI()和encodeURICompo ...