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

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. ASP.NET MVC创建视图过程

    MvcHandler.ProcessRequest()   (1)获取Action执行结果:context2.Result ActionExecutedContext context2 = this. ...

  2. Spring报错——Scope 'session' is not active for the current thread

    在对程序进行了一些修改后,运行发现spring报了这个错误,这是由于我设置了一个@Scope("session")导致的,现记录下解决方法. 解决方法: 将Scope设置为scop ...

  3. SpringMVC中重定向底层原理

      只要将数据放入model中, 也能取到值,原因是model临时放入session域中,当从定向到另一个url时,底层把数据拼接在url地址后面(重定向一定是get请求方式),同时将session域 ...

  4. 【CNMP系列】VIM编辑器详解

    缘起 大学的时候做过Linux内核驱动程序研发,之前写C语言就是用的Vim编辑器,当年的Vim还不如今天之强大,当时的插件也没有现在这么多,只是觉得这个编辑器能满足我想要的所有,查看Linux内核代码 ...

  5. centos安装python2.7并安装easy_install,pip,ipython

    1.安装python 下载python2.7.10 # wget https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz # tar -z ...

  6. JS 数组及函数

    数组    定义        Array(1,3.14,"aa")            给数据        Array(5)            给长度        [1 ...

  7. js精确计算

    官方文档:http://mikemcl.github.io/big.js/ 使用方法: x = new Big(0.1); y = x.plus(0.2); // '0.3' var a=Big(0. ...

  8. PMP和PRINCE2应该选择哪个?光环国际项目管理认证

    对于项目管理课程的选择,我们不能盲目地做选择,一定要从自身实际出发.从来都没有更好的课程,只有更合适自己的课程. 那么,如何选择合适自己的项目管理课程呢? 让我们从PMP与PRINCE2之间的差异开始 ...

  9. OpenStack及其构成简介

    新的一年新的开始,突然想学习下Openstack,之前了解过很多,但是想系统的学习一下,第一次写博客,只想把学到的东西记录下来加深印象,如有写的不好的地方请多多见谅.下面开门见山. 1.What is ...

  10. PBXCp Error

    在项目开发中遇到了报PBXcp Error错误 然后我用快捷键清理了下项目中的缓存,直接错误警告消除 多次清理缓存,我编译时用的Xcode 8.1 问题是资源文件中的nib文件找不到,有时能找到 ,有 ...