mysql 行转列分级输出_MySQL如何实现行转列分级输出?_MySQL

概述

好久没写SQL语句,今天看到问答中的一个问题,拿来研究一下。

问题链接:关于Mysql 的分级输出问题

情景简介

学校里面记录成绩,每个人的选课不一样,而且以后会添加课程,所以不需要把所有课程当作列。数据表里面数据如下图,使用姓名+课程作为联合主键(有些需求可能不需要联合主键)。本文以MySQL为基础,其他数据库会有些许语法不同。

数据库表数据:

144P1cO93K0-11F5.jpg

144P1cP1GZ-222S.jpg

处理后的结果(行转列):

144P1cP31250-31551.jpg

144P1cPDK0-42348.jpg

方法一:

这里可以使用Max,也可以使用Sum;

注意第二张图,当有学生的某科成绩缺失的时候,输出结果为Null;

SELECT

SNAME,

MAX(

CASE CNAME

WHEN 'JAVA' THEN

SCORE

END

) JAVA,

MAX(

CASE CNAME

WHEN 'mysql' THEN

SCORE

END

) mysql

FROM

stdscore

GROUP BY

SNAME;

可以在第一个Case中加入Else语句解决这个问题:

SELECT

SNAME,

MAX(

CASE CNAME

WHEN 'JAVA' THEN

SCORE

ELSE

0

END

) JAVA,

MAX(

CASE CNAME

WHEN 'mysql' THEN

SCORE

ELSE

0

END

) mysql

FROM

stdscore

GROUP BY

SNAME;

方法二:

SELECT DISTINCT a.sname,

(SELECT score FROM stdscore b WHERE a.sname=b.sname AND b.CNAME='JAVA' ) AS 'JAVA',

(SELECT score FROM stdscore b WHERE a.sname=b.sname AND b.CNAME='mysql' ) AS 'mysql'

FROM stdscore a

方法三:

DROP PROCEDURE

IF EXISTS sp_score;

DELIMITER &&

CREATE PROCEDURE sp_score ()

BEGIN

#课程名称

DECLARE

cname_n VARCHAR (20) ; #所有课程数量

DECLARE

count INT ; #计数器

DECLARE

i INT DEFAULT 0 ; #拼接SQL字符串

SET @s = 'SELECT sname' ;

SET count = (

SELECT

COUNT(DISTINCT cname)

FROM

stdscore

) ;

WHILE i < count DO

SET cname_n = (

SELECT

cname

FROM

stdscore

GROUP BY CNAME

LIMIT i,

1

) ;

SET @s = CONCAT(

@s,

', SUM(CASE cname WHEN ',

'\'',

cname_n,

'\'',

' THEN score ELSE 0 END)',

' AS ',

'\'',

cname_n,

'\''

) ;

SET i = i + 1 ;

END

WHILE ;

SET @s = CONCAT(

@s,

' FROM stdscore GROUP BY sname'

) ; #用于调试

#SELECT @s;

PREPARE stmt

FROM

@s ; EXECUTE stmt ;

END&&

CALL sp_score () ;

处理后的结果(行转列)分级输出:

144P1cPW50-5E16.jpg

144P1cQ250-EL6.jpg

方法一:

这里可以使用Max,也可以使用Sum;

注意第二张图,当有学生的某科成绩缺失的时候,输出结果为Null;

SELECT

SNAME,

MAX(

CASE CNAME

WHEN 'JAVA' THEN

(

CASE

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') > 20 THEN

'优秀'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') > 10 THEN

'良好'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') >= 0 THEN

'普通'

ELSE

'较差'

END

)

END

) JAVA,

MAX(

CASE CNAME

WHEN 'mysql' THEN

(

CASE

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') > 20 THEN

'优秀'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') > 10 THEN

'良好'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') >= 0 THEN

'普通'

ELSE

'较差'

END

)

END

) mysql

FROM

stdscore

GROUP BY

SNAME;

方法二:

SELECT DISTINCT a.sname,

(SELECT (

CASE

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') > 20 THEN

'优秀'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') > 10 THEN

'良好'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') >= 0 THEN

'普通'

ELSE

'较差'

END

) FROM stdscore b WHERE a.sname=b.sname AND b.CNAME='JAVA' ) AS 'JAVA',

(SELECT (

CASE

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') > 20 THEN

'优秀'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') > 10 THEN

'良好'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME='JAVA') >= 0 THEN

'普通'

ELSE

'较差'

END

) FROM stdscore b WHERE a.sname=b.sname AND b.CNAME='mysql' ) AS 'mysql'

FROM stdscore a

方法三:

DROP PROCEDURE

IF EXISTS sp_score;

DELIMITER &&

CREATE PROCEDURE sp_score ()

BEGIN

#课程名称

DECLARE

cname_n VARCHAR (20) ; #所有课程数量

DECLARE

count INT ; #计数器

DECLARE

i INT DEFAULT 0 ; #拼接SQL字符串

SET @s = 'SELECT sname' ;

SET count = (

SELECT

COUNT(DISTINCT cname)

FROM

stdscore

) ;

WHILE i < count DO

SET cname_n = (

SELECT

cname

FROM

stdscore

GROUP BY CNAME

LIMIT i, 1

) ;

SET @s = CONCAT(

@s,

', MAX(CASE cname WHEN ',

'\'',

cname_n,

'\'',

' THEN (

CASE

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME=\'',cname_n,'\') > 20 THEN

\'优秀\'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME=\'',cname_n,'\') > 10 THEN

\'良好\'

WHEN SCORE - (select avg(SCORE) from stdscore where CNAME=\'',cname_n,'\') >= 0 THEN

\'普通\'

ELSE

\'较差\'

END

) END)',

' AS ',

'\'',

cname_n,

'\''

) ;

SET i = i + 1 ;

END

WHILE ;

SET @s = CONCAT(

@s,

' FROM stdscore GROUP BY sname'

) ;

#用于调试

#SELECT @s;

PREPARE stmt

FROM

@s ; EXECUTE stmt ;

END&&

CALL sp_score ();

几种方法比较分析

第一种使用了分组,对每个课程分别处理。

第二种方法使用了表连接。

第三种使用了存储过程,实际上可以是第一种或第二种方法的动态化,先计算出所有课程的数量,然后对每个分组进行课程查询。这种方法的一个最大的好处是当新增了一门课程时,SQL语句不需要重写。

小结

关于行转列和列转行

这个概念似乎容易弄混,有人把行转列理解为列转行,有人把列转行理解为行转列;

这里做个定义:

行转列:把表中特定列(如本文中的:CNAME)的数据去重后做为列名(如查询结果行中的“JAVA,mysql”,处理后是做为列名输出);

列转行:可以说是行转列的反转,把表中特定列(如本文处理结果中的列名“JAVA,mysql”)做为每一行数据对应列“CNAME”的值;

关于效率

不知道有什么好的生成模拟数据的方法或工具,麻烦小伙伴推荐一下,抽空我做一下对比;

还有其它更好的方法吗?

本文使用的几种方法应该都有优化的空间,特别是使用存储过程的话会更加灵活,功能更强大;

本文的分级只是给出一种思路,分级的方法如果学生的成绩相差较小的话将失去意义;

如果小伙伴有更好的方法,还请不吝赐教,感激不尽!

有些需求可能不需要联合主键

有些需求可能不需要联合主键,因为一门课程可能允许学生考多次,取最好的一次成绩,或者取多次的平均成绩。

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/326567.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2017蓝桥杯省赛---java---B---7(日期问题)

题目描述 日期问题 标题&#xff1a;日期问题小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在1960年1月1日至2059年12月31日。令小明头疼的是&#xff0c;这些日期采用的格式非常不统一&#xff0c;有采用年/月/日的&#xff0c;有采用月/日/…

ssm使用全注解实现增删改查案例——DeptMapperImpl

package org.dao.impl;import java.util.List;import org.dao.IDeptMapper; import org.entity.Dept; import org.springframework.beans.factory.annotation.Autowired;public class DeptMapperImpl implements IDeptMapper {//自动注入Autowiredprivate IDeptMapper deptMapp…

Gson的入门使用

转载自 Gson的入门使用 Java对象和Json之间的互转&#xff0c;一般用的比较多的两个类库是Jackson和Gson&#xff0c;下面记录一下Gson的学习使用。 基础概念&#xff1a; Serialization:序列化&#xff0c;使Java对象到Json字符串的过程。 Deserialization&#xff1a;反序…

Visual Studio 2017正式版离线安装及介绍

Visual Studio 2017 RTM正式版离线安装及介绍。 首先至官网下载&#xff1a;https://www.visualstudio.com/zh-hans/downloads/ VS 2017 正式版介绍&#xff1a; https://www.visualstudio.com/zh-hans/vs/whatsnew/ VS 2017 离线模式只离线.NET Core部分&#xff1a; Visual S…

ssm使用全注解实现增删改查案例——EmpMapperImpl

package org.dao.impl;import java.util.List;import org.dao.IEmpMapper; import org.entity.Emp; import org.springframework.beans.factory.annotation.Autowired;public class EmpMapperImpl implements IEmpMapper {//自动注入Autowiredprivate IEmpMapper empMapper;/*…

Linux下查找命令

转载自 Linux下查找命令 一.Linux查找文件的相关命令 常 用 命 令 简要中文说明 程序所在目录 more 分页显示一个文件或任何输出结果 /bin less 分页显示一个文件并且可以回头 /usr/bin whereis 寻找文件工具 /usr/bin find 寻找文件工具 /usr/bin locate 寻…

wadl2java cxf_java – CXF JAXRS |生成的wadl中不存在复杂响应类型

我们使用cxf 2.5.2和spring来暴露和消费宁静的服务.为了分发服务接口类,我们开始使用wadl2java目标(根据给定的wadl文件生成接口类)生成的wadl不包含正确的响应类型,因为我猜测,生成的接口都有’Response’作为返回类型.防爆.如果restful get方法返回’List’,则生成的wadl仅包…

Visual Studio 2017 新功能(上)

开发&#xff1a;快速导航、编写并修复代码 新的安装体验 - 降低了最小内存需求量以实现更快、更定制化的安装&#xff0c;并且支持脱机安装。 Visual Studio IDE - 大幅改进了 Visual Studio 2017&#xff0c;包括减少启动和解决方案加载时间、改进登录和标识、改进代码导航以…

2018蓝桥杯省赛---java---B---1(第几天)

题目描述 思路分析 31 29 31 30 4 125 答案 125

ssm使用全注解实现增删改查案例——Dept

package org.entity;import java.util.List; /*** * * 项目名称&#xff1a;test_myabtis_zhujie * 类名称&#xff1a;Dept * 类描述&#xff1a; 部门表的实体类 * 创建人&#xff1a;Mu Xiongxiong * 创建时间&#xff1a;2018-3-16 下午4:33:10 * 修改人…

mysql 数据库引擎

转载自 mysql 数据库引擎 数据库引擎介绍 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的。要添加一个新的引擎&#xff0c;就必须重新编译MYSQL。在缺省情况下&#xff0c;MYSQL支持三个引擎&#xff1a;ISAM、MYISAM和HEAP。另外两种类型INNODB和BERKLEY&#xff0…

java 组件化_(原创)搭建一个组件化的监控平台

最近看到一位同事正在开发一个监控软件&#xff0c;要求就是通过针对服务器现有的一些接口&#xff0c;通过这些接口返回的数据进行分析&#xff0c;如果监控的值到达预先设定的范围则通过短信的方式发送给管理员。从整个开发的功能上来看是一个比较单一也很明确的功能&#xf…

微软发招,苹果发飙,React Native躺枪

这两天苹果和微软互怼&#xff0c;用脚本热更新的朋友要谨慎过 iOS 审核。 早上有Q群里面在讨论最近用 JavaScript 做为脚本层&#xff0c;在苹果商店审核遭拒的情况。 从目前多数信息来看&#xff0c;cocos2d-js 和 creator 这样用 SpiderMonkey JSB 技术栈的游戏情况尚好&am…

ssm使用全注解实现增删改查案例——Emp

package org.entity;import java.util.Date; /*** * * 项目名称&#xff1a;test_myabtis_zhujie * 类名称&#xff1a;Emp * 类描述&#xff1a; 员工信息表 * 创建人&#xff1a;Mu Xiongxiong * 创建时间&#xff1a;2018-3-16 下午4:34:02 * 修改人&…

2018蓝桥杯省赛---java---B---2(方格计数)

题目描述 思路分析 圆的对称性 代码实现 package com.atguigu.TEST;class Main{public static void main(String[] args) {int ans0;for (int i 1; i < 1000; i) {for (int j 1; j < 1000; j) {if(i*ij*j<1000*1000){ans;}}}System.out.println(ans*4);//向四边发…

MySQL 5.7 聚合(GROUP BY)功能描述

转载自 MySQL 5.7 聚合&#xff08;GROUP BY&#xff09;功能描述 12.19.1聚合&#xff08;GROUP BY&#xff09;功能描述 本节介绍对值集合进行操作的组&#xff08;聚合&#xff09;函数。 表12.25聚合&#xff08;GROUP BY&#xff09;函数 名称描述AVG()返回参数的平均…

python的pandas库中如何计算每列出现最多的值_Python Pandas:计算多个列的每个唯一值的显示次数...

假设我有一个DataFrame,如,In [7]: source pd.DataFrame([[amazon.com, correct, correct], [amazon.com, incorrect, correct], [walmart.com, incorrect, correct], [walmart.com, incorrect, incorrect]], columns[domain, price, product])In [8]: sourceOut[8]:domain pr…

Visual Studio 2017 新功能(下)

调试和诊断 运行时单击 只需在调试运行到此行时单击代码行旁边的图标。 无需再设置临时断点&#xff0c;也不必再执行多个步骤来执行代码和在所需行停止。 现在&#xff0c;调试器下停在中断状态时&#xff0c;“运行时单击”图标会在鼠标悬停位置的代码行旁边巧妙显示。 将鼠…

ssm使用全注解实现增删改查案例——IDeptService

/** * Title: IDeptService.java * Package org.service * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2018-3-12 上午10:45:56 * version V1.0 */ package org.service;import java.util.List;import org.entity.Dept;/…

2018蓝桥杯省赛---java---B---3(复数幂)

题目描述 思路分析 代码实现 package com.atguigu.TEST;import java.io.File; import java.io.FileNotFoundException; import java.io.PrintStream; import java.math.BigInteger;class Main{public static void main(String[] args) {BigInteger two BigInteger.valueOf(2)…