MySQL怎么实现行转列SQL

2023-11-19

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

情景:

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

数据库表数据:

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

方法一:

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

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

[sql] view plain copy

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语句解决这个问题:

[sql] view plain copy

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;

方法二:

[sql] view plain copy

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

方法三:

[sql] view plain copy

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 () ;

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

方法一:

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

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

[sql] view plain copy

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;

方法二:

[sql] view plain copy

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

方法三:

[sql] view plain copy

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”的值;

关于效率

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

还有其它更好的方法吗?

————————————————

来源:https://www.weidianyuedu.com

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL怎么实现行转列SQL 的相关文章

  • 我可以使用 HSQLDB 进行 junit 测试克隆 mySQL 数据库吗

    我正在开发一个 spring webflow 项目 我想我可以使用 HSQLDB 而不是 mysql 进行 junit 测试吗 如何将我的 mysql 数据库克隆到 HSQLDB 如果您使用 spring 3 1 或更高版本 您可以使用 s
  • 映射 mysql 中同一个表的多个值

    您好 我必须使用另一个表中的值 id 获取文本值 表 1 包含值 ID 表 2 包含名称和值 ID 表 1 SEVERITY OCCURENCE DETECTABILITY 2 3 4 表 2 id name value 1 Very Hi
  • 如何修改现有表以添加时区

    我有一个包含 500 多个表的大型应用程序 我必须将应用程序转换为时区感知 当前应用程序使用new java util Date GETDATE 与服务器的时区 即没有任何时区支持 我已将这项任务分为几个步骤 以便于开发 我确定的第一个步骤
  • Mysql 时间匹配连接

    我有两个表cpuinfo和jobinfo 我想使用这两种数据创建报告 tabes CREATE TABLE cpuinfo id int 11 NOT NULL AUTO INCREMENT usagetime datetime DEFAU
  • 从按日期时间排序的 MySQL 表中获取用户的最后一个条目

    我有一张看起来像这样的桌子 USERNAME DATA DATETIME Jhon text1 2010 06 01 16 29 43 Mike text2 2010 06 01 16 29 22 Silver text3 2010 05
  • 仅当值发生更改时如何插入数据库?

    我需要更新 替换 MySQL 数据库中的字段 但前提是它们已更改 该表包含 ID 文本字段和更改日期 用户根据更改日期通过 ID 查询数据 即 如果该日期早于用户上次查询数据的时间 则他不想要它 仅当文本字段与具有相同 ID 的现有文本字段
  • MySQL - 从临时表插入

    这看起来非常简单 但我坚持使用简单的插入语句 见下文 begin work CREATE TEMPORARY TABLE IF NOT EXISTS insert table AS select r resource id fr file
  • 如果没有找到值,如何让 MySQL 中的 SUM 函数返回“0”?

    假设我在 MySQL 中有一个简单的函数 SELECT SUM Column 1 FROM Table WHERE Column 2 Test 如果没有条目Column 2 包含文本 Test 然后该函数返回NULL 而我希望它返回 0 我
  • MySQL 通过 current_timestamp 选择上个月的数据

    直到今天 当我使用 MySQL 并需要对日期 时间执行操作时 我使用带有 unix 时间戳的 int 列 没有出现任何问题 但今天在阅读了一些指南后 我决定默认使用 current timestamp 测试时间戳列 所以我感兴趣如何按列选择
  • mysql转储到derby

    我正在使用 derby 在 eclipse 中进行开发 是否可以从 MySQL 转储表并以某种方式将其用于 derby 我知道 ddl 和 dml 对于两个 dbms 来说是不同的 但我正在寻找一种除了转储 导出之外的合适方法 我可以找到两
  • PHP MYSQL文件内容转义问题

    我正在尝试使用 php 将 pdf 文件上传到 mysql 数据库中 除了文件内容之外 一切都很好 无论我如何尝试转义特殊字符 查询总是失败 主要是 未知命令 n 我使用过addslashes mysql real escape strin
  • PHP PDO 使用 bindParam 第一个参数(不带冒号)[重复]

    这个问题在这里已经有答案了 请检查这个 user id int GET user id sql DELETE FROM users WHERE user id user id query db gt prepare sql query gt
  • MySQL 排序顺序 - 排序规则?

    我在对 MySQL 中的 char 字段进行排序时遇到困难 问题是重音字符与非重音字符混淆 例如 Abc bd Acc 我认为这可能与整理有关 所以我将表格的排序规则更改为utf8 ut8 bin 看完之后这个帖子 https stacko
  • 将庞大数据库从亚马逊RDS导出到本地mysql

    我在 Amazon RDS 上有一个 mysql 数据库 大约 600GB 数据 我需要将其移回本地专用服务器 但我不知道从哪里开始 每次我尝试初始化 sqldump 时它都会冻结 有没有办法将其移至 S3 甚至可能在开始下载之前将其分成更
  • MySQL/PDO::quote() 尽管使用 PDO::PARAM_INT 参数,但仍在整数周围加上引号

    无论我传递给什么值 数据类型对 它都会出现 pdo gt quote value type 它总是将其引用为字符串 echo pdo gt quote foo PDO PARAM STR foo as expected echo pdo g
  • 删除行导致锁超时

    当我尝试从表中删除行时 我不断收到这些错误 这里的特殊情况是我可能同时运行5个进程 该表本身是一个 Innodb 表 约有 450 万行 我的 WHERE 子句中使用的列没有索引 其他指数按预期运行 这是在事务中完成的 首先删除记录 然后插
  • 如何通过Elasticsearch模糊匹配电子邮件或电话?

    我想通过 Elasticsearch 对电子邮件或电话进行模糊匹配 例如 匹配所有以以下结尾的电子邮件 gmail com or 匹配所有电话开头136 我知道我可以使用通配符 query wildcard email gmail com
  • MySQL 与日语字符

    我试图弄清楚如何创建一个表 以便我可以在其中插入日语名字 现在我有 Type InnoDB Encoding UTF 8 Unicode utf8 Collation utf8 general ci 但是 当我插入字符时 它显示为 当我使用
  • 在 android 中建立与 MySQL 的池连接

    我需要从我的 Android 应用程序访问 MySQL 数据库 现在所有的工作都通过 DriverManager getConnection url 等等 但我必须从多个线程访问数据库 所以我必须使用连接池 问题1 是 com mysql
  • 快速将列的副本添加到 MySQL 表

    我需要一种快速的方法来复制表中的 DATETIME 列并为其指定一个新名称 我的表中有一个名为 myDate 的列 名为 myResults 我需要一个查询来在名为 newDate 的表中创建一个新列 该列的数据与 myDate 列完全相同

随机推荐

  • abc300.com站点被注入脚本

    在进行abc300 com的页面SEO时发现 所有页面受到注入攻击 全部asp页最后被添加一页 弄了1个多小时 大部份页面被清除 目前已经获得www hulijie com的ftp 222 33 63 206 用户名admin 密码尚需分析
  • postgresql 高可用框架对比

    PostgreSQL 的高可用框架有许多种 每种都有其独特的优缺点 下面是一些常见的高可用框架的对比 Pgpool II 这是一个开源的负载均衡和数据库代理 支持主从复制和读写分离 它的优点在于易于安装和使用 缺点是不支持实时备份 Repm
  • Log4Net 日志管理

    Log4Net日志管理 A Log4Net日志管理 Log4Net的日志级别如下 级别 允许的方法 Boolean属性 优先级别 OFF Highest FATAL void Fatal bool IsFatalEnabled RROR v
  • 函数的节流与防抖

    1 节流 节流的意思是 规定时间内 只触发一次 比如我们设定500ms 在这个时间内 无论点击按钮多少次 它都只会触发一次 具体场景可以是抢购时候 由于有无数人 快速点击按钮 如果每次点击都发送请求 就会给服务器造成巨大的压力 但是我们进行
  • C语言-求因子和

    求因子和 题目描述 一个数的因子和不包括它本身的所有因子之和 如12的因子有1 2 3 4 6所以12的因子和是16 现在给定一个数n n lt 10 9 求它的因子和 输入格式 一个数 输出格式 一个数 样例输入 12 样例输出 16 提
  • 有趣的MyBatis——延迟加载

    为什么80 的码农都做不了架构师 gt gt gt 我们知道在resultMap中使用级联对于查找相关数据来说很方便 比如说查找雇员基本信息 顺便得到了雇员的体检信息 家庭信息 部门信息 但是有时我们不需要相关数据 那么在一些复杂的系统中
  • 初学MaxCompute

    MaxComputer是阿里云提供的一种全新的大数据计算服务 其具备更高效的计算及存储能力 本人的理解就是一个类似于HBase Hive的云上的数据仓库 参考官方文档系列 https yq aliyun com articles 85595
  • “ping“不是内部或外部命令,也不是可运行的程序 或批处理文件。

    输入ping 出现问题 ping 不是内部或外部命令 也不是可运行的程序或批处理文件 我的电脑 属性 高级系统设置 环境变量 系统变量 PATH 编辑 输入C Windows System32 再次输入ping 即表示可以了
  • 数据迁移时,需要大量set时的批量操作

    我遇到了一种情况 A类有很多的数据 需要迁移到新的A类或者和字段和A类相同的数据 例如 A1 A2 A3 A4 A100 需要进行批量操作 A1 gt 例 加密 A2 gt 加密 每个字段或部分字段都需要加密 那么正常的情况下需要有多少字段
  • C语言入门

    什么是C语言 C语言是一门通用计算机编程语言 广泛应用于底层开发 C语言的设计目标是提供一种能以简易 的方式编译 处理低级存储器 产生少量的机器码以及不需要任何运行环境支持便能运行的编程 语言 尽管C语言提供了许多低级处理的功能 但仍然保持
  • 谈谈BFC

    谈谈BFC 介绍 BFC Block Formatting Context 块级格式化上下文 它理解成一个独立的区域 此区域里面的子元素不会影响到外面的元素 反之也如此 BFC布局规则 内部的Box会在垂直方向 一个接一个地放置 Box垂直
  • 服务器选哪个系统,服务器选择哪个操作系统

    服务器选择哪个操作系统 内容精选 换一换 裸金属服务器在详情页面显示的云硬盘设备名称与操作系统内部的设备名称不一致 为防止设备名称变化对业务造成影响 建议通过UUID的方式使用云硬盘 当携带云硬盘创建裸金属服务器完成后 裸金属服务器详情界面
  • DenyHosts安装与部署

    DenyHosts是Python语言写的一个程序软件 运行于Linux上预防SSH暴力破解的 它会分析sshd的日志文件 var log secure 当发现重复的攻击时就会记录IP到 etc hosts deny文件 从而达到自动屏IP的
  • Http协议详解

    引入 超文本传输协议 HTTP HyperText Transfer Protocol 是互联网上应用最为广泛的一种网络协议 所有的WWW文件都必须遵守这个标准 设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法 1960年美
  • 日赚4.12亿,腾讯最新员工薪酬公布:均薪破100万!!!

    近日 腾讯发布2023年第二季度财报 有一项数据冲上热搜 引起热议 据计算 腾讯人均年薪破100万 网友直呼 酸了酸了 这是认真的吗 跟随播妞一起来看看吧 腾讯员工平均年薪达100万 从大厂财报看互联网行业回暖之势 近日 腾讯发布截至6月3
  • [Python]保姆级win11环境安装Python

    1 下载安装包 https www python org downloads 选择自己的系统对应的安装包 我的是Windows系统 我就直接选择它了 选择64位安装包 根据自己系统对应的安装包 2 开始安装 去下载路径下 双击源文件 开始安
  • LeetCode第321场周赛题解

    这周周赛没有什么过多难的 也是可以自己写完的 芜湖 第一道题 6245 找出中枢整数 给你一个正整数 n 找出满足下述条件的 中枢整数 x 1 和 x 之间的所有元素之和等于 x 和 n 之间所有元素之和 返回中枢整数 x 如果不存在中枢整
  • Android之RecyclerView多布局

    做一个项目的主页面的时候 想要它呈现出来的效果 不单一 更丰富那就要使用多布局来展现出来 那么就要思考一个问题 他呈现的是多个布局 怎么才能展现出来不同的布局 逻辑很简单 通过设置几个flag 来表示这些布局当前显示的是哪个布局 接下来 和
  • 使用python对光谱数据进行lorentz峰值拟合(bounds限定拟合参数范围)

    1 lorentz峰值拟合 发光光谱是一种用于表征二维半导体材料光学性质的重要技术 它可以反映出材料中的载流子密度 缺陷态 激子束缚能等信息 由于二维半导体材料的厚度极其薄 其发光信号往往很弱 且受到基底 环境和测量设备等因素的干扰 因此需
  • MySQL怎么实现行转列SQL

    问题 关于Mysql 的分级输出问题 情景 学校里面记录成绩 每个人的选课不一样 而且以后会添加课程 所以不需要把所有课程当作列 数据表里面数据如下图 使用姓名 课程作为联合主键 有些需求可能不需要联合主键 本文以MySQL为基础 其他数据