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 ...
随机推荐
- Node.js连接mysql报加密方式错误解决方案
本人在学习全栈开发过程中做一个Node的web项目在连接本地MySQL8.0版本的数据库时,发现Navicat连接不上,它报了一个数据库的加密方式导致连接不上的错误,错误如下: MySQL8.0版本的 ...
- pytorch中的view
https://ptorch.com/news/59.html view()相当于reshape(),其中参数若为-1表示当前的size根据其余size推断
- 服务器配置iis,php网站
1.在iis中选择物理路径.配置域名 2.添加php默认文档 3.修改处理程序映射 4.设置模块映射信息
- PAT (Basic Level) Practise (中文)- 1024. 科学计数法 (20)
PAT (Basic Level) Practise (中文)- 1024. 科学计数法 (20) http://www.patest.cn/contests/pat-b-practise/1024 ...
- 风格附加css
#header #blogTitle { background: url("http://images.cnblogs.com/cnblogs_com/aiwuxia/1249780/o_1 ...
- Fisherfaces 算法的具体实现源码
/* * Copyright (c) 2011. Philipp Wagner <bytefish[at]gmx[dot]de>. * Released to public domain ...
- Java--返回类的对象(return this)
如下代码所示: public Book getBook(){ return this; } 在getBook()方法中,方法的返回值为Book类,所以方法体中使用 return this 这种形式返回 ...
- HDU-1455-木棒
这题的话,我们,定义一个结构体,然后把木棒从大到小排序. 这些木棒如果是由多根等长木棒组成的,那目标长度一定大于等于其中最长的木棒长度,所这就是我们搜索的下限. 上限就是所有的木棒组成了一根木棒,就是 ...
- 【Java_基础】java中static与final关键字的区别
1.static关键字 经static关键字修饰的成员被该类的所有对象所共享,任意一对象对静态变量的修改其它对象都是可见的.通常通过类名来引用static成员.类加载的连接阶段将会为静态成员变量在jv ...
- django(django项目创建,数据库迁移)
Django项目的创建与介绍 安装:pip3 install django==1.11 查看版本号:django-admin --version 新建项目: 1.切到目标目录 2.django-adm ...