情景简介

学校里面记录成绩,每个人的选课不一样,而且以后会添加课程,所以不需要把所有课程当作列。数据库grade里面数据如下图,假定每个人姓名都不一样,作为主键。本文以MySQL为基础,其他数据库会有些许语法不同。

数据库数据:

mysql> select * from grade;
+------+--------+--------+-------+
| id | name | course | score |
+------+--------+--------+-------+
| 1 | 张三 | 语文 | 80 |
| 2 | 张三 | 数学 | 90 |
| 3 | 张三 | 英语 | 90 |
| 4 | 李四 | 语文 | 47 |
| 5 | 李四 | 数学 | 78 |
| 6 | 王五 | 数学 | 97 |
+------+--------+--------+-------+
6 rows in set (0.00 sec) mysql>

处理后效果:

+--------+--------+--------+--------+
| name | 语文 | 数学 | 英语 |
+--------+--------+--------+--------+
| 张三 | 80 | 90 | 90 |
| 李四 | 47 | 78 | NULL |
| 王五 | NULL | 97 | NULL |
+--------+--------+--------+--------+
3 rows in set (0.00 sec) mysql>

下面介绍三种方法:

方法一:

SELECT DISTINCT  a.name,
(SELECT score FROM grade b WHERE a.name=b.name AND b.course='语文' ) AS '语文',
(SELECT score FROM grade b WHERE a.name=b.name AND b.course='数学' ) AS '数学',
(SELECT score FROM grade b WHERE a.name=b.name AND b.course='英语' ) AS '英语'
FROM grade a

方法二:

SELECT name,
SUM(CASE course WHEN '语文' THEN score END ) AS '语文',
SUM(CASE course WHEN '数学' THEN score END ) AS '数学',
SUM(CASE course WHEN '英语' THEN score END ) AS '英语'
FROM grade GROUP BY name

方法三:

DELIMITER &&
CREATE PROCEDURE sp_count()
BEGIN
#课程名称
DECLARE course_n VARCHAR(20);
#所有课程数量
DECLARE count INT;
#计数器
DECLARE i INT DEFAULT 0;
#拼接SQL字符串
SET @s = 'SELECT name';
SET count = (SELECT COUNT(distinct course) FROM grade);
WHILE i < count DO
SET course_n = (SELECT course FROM grade LIMIT i,1);
SET @s = CONCAT(@s, ', SUM(CASE course WHEN ','\'', course_n,'\'',' THEN score END )',' AS ','\'',course_n,'\'');
SET i = i+1;
END WHILE;
SET @s = CONCAT(@s, ' FROM grade GROUP BY name');
#用于调试
#SELECT @s;
PREPARE stmt FROM @s;
EXECUTE stmt;
END
&& call sp_count();

方法分析:

第一种方法使用了表连接。
第二种使用了分组,对每个分组分别处理。
第三种使用了存储过程,其实是第二种方法的动态化,先计算出所有课程的数量,然后对每个分组进行课程查询。
很明显前两种方法属于硬编码,增加课程后就需要修改SQL。而第三种则没有这种问题。

Note:

MySQL中不能在一个存储过程中删除另一个存储过程,只能调用另一个存储过程
本来想在方法三里面写上:DROP PROCEDURE IF EXISTS sp_count();这是错误的。调试的时候如果写错了,只能手动删除了,也没找到好方法。

结果转出行或者一个拼接字符串:mysql函数之五:group_concat mysql 把结果集中的一列数据用指定分隔符转换成一行

二、列转行

原来是这样
名称 单价 进货价
内存 120 100 现在想这样
名称 价格
内存 120
内存 100
mysql> select * from device_info;
+--------+--------+-----------+
| dname | danjia | jinhuojia |
+--------+--------+-----------+
| 内存 | 100 | 80 |
| CPU | 200 | 150 |
| 硬盘 | 300 | 230 |
+--------+--------+-----------+
3 rows in set (0.00 sec) mysql>

sql:

mysql> SELECT * FROM
-> (SELECT dname, danjia AS jiage FROM device_info
-> UNION ALL
-> SELECT dname,jinhuojia AS jiage FROM device_info) AS temp
-> ORDER BY dname;
+--------+-------+
| dname | jiage |
+--------+-------+
| CPU | 150 |
| CPU | 200 |
| 内存 | 80 |
| 内存 | 100 |
| 硬盘 | 230 |
| 硬盘 | 300 |
+--------+-------+
6 rows in set (0.03 sec) mysql>

经典SQL问题: 行转列,列转行的更多相关文章

  1. sql 多行转多列,多行转一列合并数据,列转行

    下面又是一种详解:

  2. SQL多行转多列

    --★转换结果如上图 1.首先创建表: CREATE TABLE [成绩表]( ,) NOT NULL, )NULL, , )NULL, , )NULL, , )NULL ) ON [PRIMARY] ...

  3. 【收藏】SQL多行变一列

    CREATE TABLE DEPT (DeptNo INT IDENTITY(1, 1)NOT NULL ,  Country VARCHAR(50) ,  Location VARCHAR(50) ...

  4. SQL多行变一列

    CREATE TABLE DEPT (DeptNo INT IDENTITY(1, 1)NOT NULL ,  Country VARCHAR(50) ,  Location VARCHAR(50) ...

  5. sql多行合并一列

    with a as( select * from( select 1 userId , '天津' province union select 1 userId , '北京' union select ...

  6. SQL Server 行转列,列转行。多行转成一列

    一.多行转成一列(并以","隔开) 表名:A 表数据: 想要的查询结果: 查询语句: SELECT name , value = ( STUFF(( SELECT ',' + va ...

  7. sql的行转列(PIVOT)与列转行(UNPIVOT) webapi 跨域问题 Dapper 链式查询 扩展 T4 代码生成 Demo (抽奖程序)

    sql的行转列(PIVOT)与列转行(UNPIVOT)   在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比 ...

  8. SQL Server 行转列,列转行

    一.多行转成一列(并以","隔开) 表名:A 表数据: 想要的查询结果: 查询语句: SELECT name , value = ( STUFF(( SELECT ',' + va ...

  9. Sql server 中将数据行转列列转行(二)

    老规矩,先弄一波测试数据,数据填充代码没有什么意义,先折叠起来: /* 第一步:创建临时表结构 */ CREATE TABLE #Student --创建临时表 ( StuName ), --学生名称 ...

  10. 在mybatis中使用存储过程报错java.sql.SQLException: ORA-06550: 第 1 行, 第 7 列: PLS-00905: 对象 USER1.HELLO_TEST 无效 ORA-06550: 第 1 行, 第 7 列:

    hello_test是我的存储过程的名字,在mapper.xml文件中是这么写的 <select id="getPageByProcedure" statementType= ...

随机推荐

  1. matlab第一个小应用

    今天安装了matlab,以前还是上线性代数的时候,老师让用过,以及水了一次数模的时候玩了一下.以前太年轻,总觉得这个用处不大虽然别人一直强调这个神器... 到了自己要用的时候才会意识到.大家可能也都听 ...

  2. Luogu-3878 [TJOI2010]分金币

    这题和在我长郡考试时的一道题思路差不多...考虑折半搜索,预处理左半边选的方案所产生的数量差值\(x\)以及价值差值\(y\),把\(y\)扔到下标为\(x\)的set里面,然后在搜索右半边,每搜出一 ...

  3. mysql基础(1)-基本操作

    数据库 数据库(Database,DB)是数据的集合,是一个长期存储在计算机内的.有组织的.有共享的.统一管理的数据集合. 存储数据 管理数据 数据库类型 关系型数据库:由二维表及其之间的联系组成的一 ...

  4. 广西邀请赛 B+K

    B是一个看起来很KDT的题  但是因为KDT是n^1.5的所以t  而且因为KDT需要周期性的重建所以复杂度会更高 因为只有51种颜色 所以想当然的就去想了状态压缩 因为询问的区间范围 x一定是从1开 ...

  5. Unity3D-UGUI图集打包与动态使用(TexturePacker)

    参考地址: http://blog.csdn.net/cjsen/article/details/52487706 今天做项目大佬看我在做图集,就跟我说可以用工具打包图集,也就是TexturePack ...

  6. [转载]Java开发在线打开编辑保存Word文件

    Java调用logo是“P”图标的第三方插件,实现在线编辑保存Word文件(以jsp调用为例,支持SSM.SSH.SpringMVC等流行框架) 工具/原料   Eclipse或MyEclipse等j ...

  7. hdu-3068-最长回文(manacher算法模板)

    题目链接 /* Name:hdu-3068-最长回文 Copyright: Author: Date: 2018/4/24 16:12:45 Description: manacher算法模板 */ ...

  8. Redis 高可用及分片集群,说了你也不懂

    Redis 简介 Memcached: 优点:高性能读写.单一数据类型.支持客户端式分布式集群.一致性hash 多核结构.多线程读写性能高. 缺点:无持久化.节点故障可能出现缓存穿透.分布式需要客户端 ...

  9. Scala极速入门

    摘要 当面向对象遇到函数式编程,这就是Scala.简练的语言描述与简单的例子相辅相成,希望能够对大家学习Scala有所帮助. scala 入门 定义 Scala语言是一种面向对象语言,同时又结合了命令 ...

  10. 转载:java电商面试介绍(不完整版)

    转载: http://blog.csdn.net/xue_mind/article/details/52959107