SQL行转列 (及EAV模型获取数据)
参考文章:
http://www.williamsang.com/archives/1508.html
情景简介
学校里面记录成绩,每个人的选课不一样,而且以后会添加课程,所以不需要把所有课程当作列。数据库grade里面数据如下图,假定每个人姓名都不一样,作为主键。本文以MySQL为基础,其他数据库会有些许语法不同。
数据库数据:
处理后效果:
下面介绍三种方法:
方法一:
|
1
2
3
4
5
|
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 |
方法二:
|
1
2
3
4
5
|
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 |
方法三:
|
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
|
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 DOSET 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();这是错误的。调试的时候如果写错了,只能手动删除了,也没找到好方法。
参考资料:
2013-8-8更新:
方法二还可以使用IF语句。
如下所示:
|
1
2
3
4
5
|
SELECT name,SUM(IF (course = '语文' , score , null ) ) as '语文',SUM(IF (course = '数学' , score , null ) ) as '数学',SUM(IF (course = '英语' , score , null ) ) as '英语 'FROM grade GROUP BY name |
IF(expr1,expr2,expr3),如果expr1是TRUE(expr1<>0且expr1<>NULL),那么IF()返回expr2,否则它返回expr3。IF()返回一个数字或字符串值,取决于它被使用的上下
方法四:使用多次 自连接 (每多一行转列都多一次inner join)
SELECT `main_table`.*,`table_name`.`value` AS `name`,`table_name2`.`value` AS `url_path`
FROM `catalog_category_entity` AS `main_table`
INNER JOIN `catalog_category_entity_varchar` AS `table_name` ON `table_name`.`entity_id`=`main_table`.`entity_id`
INNER JOIN `catalog_category_entity_varchar` AS `table_name2` ON `table_name2`.`entity_id`=`main_table`.`entity_id`
WHERE 1=1
AND (`table_name`.`attribute_id` = (41))
AND (`table_name2`.`attribute_id` = (57))
AND (`main_table`.`parent_id` = (2))
GROUP BY main_table.entity_id
SQL行转列 (及EAV模型获取数据)的更多相关文章
- SQL 行转列和列转行
SQL 行转列和列转行 行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过 ...
- Ms sql行转列。汇总
SQL行转列汇总 PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 ...
- sql 行专列 列转行 普通行列转换
转载:http://www.cnblogs.com/newwind521/archive/2010/11/25/1887203.html sql 行专列 列转行 普通行列转换 /* 标题:普通行列转换 ...
- sql 行转列 PIVOT 列转行 UNPIVOT
原文:sql 行转列 PIVOT 列转行 UNPIVOT 一: 现有表一(t_table1),想转为表二(t_table2)的格式. 表一: 年 公司 收入 2013 公司1 12 2013 公司2 ...
- sql 行转列总结
原文:sql 行转列总结 PIVOT UNPIVOT的用法 PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...
- SQL行转列,列转行
SQL 行转列,列转行 行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧. 行列转换就是如下图所示两种展示形式的互相转换 行转列 假如我们有下表: SELECT * FROM s ...
- SQL行转列和列转行
行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和 ...
- sql行转列和列转行(转)
行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和 ...
- sql 行转 列, 列转行
行列互转 复制代码 create table test(id ),quarter int,profile int) insert into test values(,,) insert into te ...
随机推荐
- PWN题搭建
0x00.准备题目 例如:level.c #include <stdio.h> #include <unistd.h> int main(){ char buffer[0x10 ...
- shell脚本,计算创建100个文件所用多少时间。
[root@localhost mulu]# ls [root@localhost mulu]# `; do touch file$i; done real 0m0.104s user 0m0.012 ...
- 基于Passthru的NDIS开发的个人理解
这几天对NDIS的学习,基本思路是:首先熟悉理论知识→然后下载一个例子进行研究→最后例子自己模仿扩展→最最后尝试自己写一个新的. Passthru是微软NDIS自己写的一个框架驱动,NDIS开发者可以 ...
- js的工厂模式
工厂模式: 什么叫工厂模式,工厂就是大家大脑里想的那样,一个流水线作业的一个东西,只需要满足刚需就可以了,一个人,只干一件事,最后串起来,就是一个事件. 首先需要说一下工厂模式.工厂模式根据抽象程度的 ...
- PAT 乙级 1009
题目 题目地址:PAT 乙级 1009 题解 本题本身属于比较简单的字符串操作题,但是因为对于string的操作和函数不熟悉导致本题做起来很费劲,需要加强对于string类以及相关方法的理解和熟练程度 ...
- 【bug】 1118 Row size too large
1118 Row size too large Every table (regardless of storage engine) has a maximum row size of 65,535 ...
- LeetCode695--岛屿的最大面积
''' 岛屿的最大面积 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被水包围着 ...
- 降维算法-PCA主成分分析
1.PCA算法介绍主成分分析(Principal Components Analysis),简称PCA,是一种数据降维技术,用于数据预处理.一般我们获取的原始数据维度都很高,比如1000个特征,在这1 ...
- MySql update inner join!MySql跨表更新 多表update sql语句?如何将select出来的部分数据update到另一个表里面?
项目中,评论数,关注数等数据,是实时更新的.+1,-1 这种. 有的时候,可能统计不准确. 需要写一个统计工具,更新校准下. 用Java写SQL和函数,代码很清晰,方便扩展,但是太慢了. 为了简单起见 ...
- js的setInterval和setTimeout的那些浅坑
setInterval和setTimeout的区别简单提一下 setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式.方法会不停地调用函数,直到 clearInterval() ...