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

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. TSQL语句和CRUD(20161016)

    上午 TSQL语句 1.创建数据库 create database test2; 2.删除数据库 drop database test2; 3.创建表 create table ceshi ( ids ...

  2. DBMS

    数据库中的概念 Catalog(分类) Table(表) Column(列)或者Field(字段) Primary(主键):唯一标识数据行的一列 业务主键:有业务意义的字段做主键 逻辑主键:使用没有任 ...

  3. canvas基础—图形变换

    1.canvas转换方法 1.1canvas转换方法 二.canvas实现图形的中心点旋转 step1:获取canva元素并指定canvas的绘图环境 var canvas=document.getE ...

  4. 【Android】TextView文字长度测量和各种Paddding解析

    老规矩,先上张图 o,这篇好像是分析篇,没有效果图.不管了,位置占着,老规矩不能坏,下面开始正文. *** 这篇博客会讲得比较杂: TextView里各部分的大小该怎么测量? 如何计算每行文字的长度? ...

  5. oracle备份脚本

    利用EXP导出全库,必须用SYSTEM或者DBA用户来导出. 具体脚本实现如下 全库导出(fullbackup): #!/bin/bash bname=`date +%Y%m%d` cd /backu ...

  6. 分块编码(Transfer-Encoding: chunked)

    参考链接: HTTP 协议中的 Transfer-Encoding 分块传输编码 一.背景: 持续连接的问题:对于非持续连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界:而对于持续连接,这种 ...

  7. 【Egret】3d 服务器配置

    在服务器MIME里添加这些类型就可以了:

  8. JavaScript高级程序设计---学习笔记(二)

    面向对象程序设计1.属性类型.定义多属性.读取属性特性对象的属性在创建时都带有一些特征值,JavaScript通过这些特征值来定义它们的行为.这些特性是为了实现JavaScript引擎用的,因此不能直 ...

  9. POPTEST老李分享session,cookie的安全性以及区别 3

    如何查看服务器端输送到我们电脑中的这些Cookie信息:      点开IE浏览器或其他浏览器,在菜单栏中有工具选项,点开有InterNet选项:          Cookie名称.来源.文件格式( ...

  10. Linux文件管理下

    文件操作 对于文件,我们可以读取(read),写入(write)和运行(execute).读取是从已经存在的文件中获得数据.写入是向新的文件或者旧的文件写入数据.如果文件储存的是可执行的二进制码,那么 ...