MySQL实验–静态行转列->动态行转列->存储过程使用行转列「建议收藏」

MySQL实验–静态行转列->动态行转列->存储过程使用行转列「建议收藏」概述 今天主要用一个实验来介绍一下在使用行转列的过程及相关实验。下面演示一下。 创建表 这里我用一个比较简单的例子来说明,也是行转列的经典例子,就是学生的成绩三张表:学生表、课程表、成绩表 1、学生…

概述

今天主要用一个实验来介绍一下在使用行转列的过程及相关实验。下面演示一下。


创建表

这里我用一个比较简单的例子来说明,也是行转列的经典例子,就是学生的成绩三张表:学生表、课程表、成绩表

1、学生表

就简单一点,学生学号、学生姓名两个字段

CREATE TABLE `student` (
 `stuid` VARCHAR(16) NOT NULL COMMENT "学号",
 `stunm` VARCHAR(20) NOT NULL COMMENT "学生姓名",
 PRIMARY KEY (`stuid`)
)
COLLATE="utf8_general_ci"
ENGINE=InnoDB;

代码100分

2、课程表

课程编号、课程名

代码100分CREATE TABLE `courses` (
 `courseno` VARCHAR(20) NOT NULL,
 `coursenm` VARCHAR(100) NOT NULL,
 PRIMARY KEY (`courseno`)
)
COMMENT="课程表"
COLLATE="utf8_general_ci"
ENGINE=InnoDB;

3、成绩表

学生学号、课程号、成绩

CREATE TABLE `score` (
 `stuid` VARCHAR(16) NOT NULL,
 `courseno` VARCHAR(20) NOT NULL,
 `scores` FLOAT NULL DEFAULT NULL,
 PRIMARY KEY (`stuid`, `courseno`)
)
COLLATE="utf8_general_ci"
ENGINE=InnoDB;

以上就是数据库表的结构了,这里没有建立外键,但是根据表的结构,可以清楚的看到成绩表中的学号和课程号是与学生表、课程表分别关联起来的。


基础数据准备

代码100分/*学生表数据*/
Insert Into student (stuid, stunm) Values("1001", "张三");
Insert Into student (stuid, stunm) Values("1002", "李四");
Insert Into student (stuid, stunm) Values("1003", "赵二");
Insert Into student (stuid, stunm) Values("1004", "王五");
Insert Into student (stuid, stunm) Values("1005", "刘青");
Insert Into student (stuid, stunm) Values("1006", "周明");
/*课程表数据*/
Insert Into courses (courseno, coursenm) Values("C001", "大学语文");
Insert Into courses (courseno, coursenm) Values("C002", "新视野英语");
Insert Into courses (courseno, coursenm) Values("C003", "离散数学");
Insert Into courses (courseno, coursenm) Values("C004", "概率论与数理统计");
Insert Into courses (courseno, coursenm) Values("C005", "线性代数");
Insert Into courses (courseno, coursenm) Values("C006", "高等数学(一)");
Insert Into courses (courseno, coursenm) Values("C007", "高等数学(二)");
/*成绩表数据*/
Insert Into score(stuid, courseno, scores) Values("1001", "C001", 67);
Insert Into score(stuid, courseno, scores) Values("1002", "C001", 68);
Insert Into score(stuid, courseno, scores) Values("1003", "C001", 69);
Insert Into score(stuid, courseno, scores) Values("1004", "C001", 70);
Insert Into score(stuid, courseno, scores) Values("1005", "C001", 71);
Insert Into score(stuid, courseno, scores) Values("1006", "C001", 72);
Insert Into score(stuid, courseno, scores) Values("1001", "C002", 87);
Insert Into score(stuid, courseno, scores) Values("1002", "C002", 88);
Insert Into score(stuid, courseno, scores) Values("1003", "C002", 89);
Insert Into score(stuid, courseno, scores) Values("1004", "C002", 90);
Insert Into score(stuid, courseno, scores) Values("1005", "C002", 91);
Insert Into score(stuid, courseno, scores) Values("1006", "C002", 92);
Insert Into score(stuid, courseno, scores) Values("1001", "C003", 83);
Insert Into score(stuid, courseno, scores) Values("1002", "C003", 84);
Insert Into score(stuid, courseno, scores) Values("1003", "C003", 85);
Insert Into score(stuid, courseno, scores) Values("1004", "C003", 86);
Insert Into score(stuid, courseno, scores) Values("1005", "C003", 87);
Insert Into score(stuid, courseno, scores) Values("1006", "C003", 88);
Insert Into score(stuid, courseno, scores) Values("1001", "C004", 88);
Insert Into score(stuid, courseno, scores) Values("1002", "C004", 89);
Insert Into score(stuid, courseno, scores) Values("1003", "C004", 90);
Insert Into score(stuid, courseno, scores) Values("1004", "C004", 91);
Insert Into score(stuid, courseno, scores) Values("1005", "C004", 92);
Insert Into score(stuid, courseno, scores) Values("1006", "C004", 93);
Insert Into score(stuid, courseno, scores) Values("1001", "C005", 77);
Insert Into score(stuid, courseno, scores) Values("1002", "C005", 78);
Insert Into score(stuid, courseno, scores) Values("1003", "C005", 79);
Insert Into score(stuid, courseno, scores) Values("1004", "C005", 80);
Insert Into score(stuid, courseno, scores) Values("1005", "C005", 81);
Insert Into score(stuid, courseno, scores) Values("1006", "C005", 82);
Insert Into score(stuid, courseno, scores) Values("1001", "C006", 77);
Insert Into score(stuid, courseno, scores) Values("1002", "C006", 78);
Insert Into score(stuid, courseno, scores) Values("1003", "C006", 79);
Insert Into score(stuid, courseno, scores) Values("1004", "C006", 80);
Insert Into score(stuid, courseno, scores) Values("1005", "C006", 81);
Insert Into score(stuid, courseno, scores) Values("1006", "C006", 82);

测试数据


纵列效果

我们一般进行成绩查询的时候看到的是这种纵列的结果

mysql> select s.stuid,s.stunm,c.coursenm,sc.scores from student s,courses c ,score sc limit 20;

 

如果要把分数这一行跟课程这一列倒转怎么办呢?


静态行转列

Select st.stuid, st.stunm, 
 MAX(CASE c.coursenm WHEN "大学语文" THEN s.scores ELSE 0 END ) "大学语文",
 MAX(CASE c.coursenm WHEN "新视野英语" THEN ifnull(s.scores,0) ELSE 0 END ) "新视野英语", 
 MAX(CASE c.coursenm WHEN "离散数学" THEN ifnull(s.scores,0) ELSE 0 END ) "离散数学",
 MAX(CASE c.coursenm WHEN "概率论与数理统计" THEN ifnull(s.scores,0) ELSE 0 END ) "概率论与数理统计",
 MAX(CASE c.coursenm WHEN "线性代数" THEN ifnull(s.scores,0) ELSE 0 END ) "线性代数",
 MAX(CASE c.coursenm WHEN "高等数学(一)" THEN ifnull(s.scores,0) ELSE 0 END ) "高等数学(一)",
 MAX(CASE c.coursenm WHEN "高等数学(二)" THEN ifnull(s.scores,0) ELSE 0 END ) "高等数学(二)"
From Student st
Left Join score s On st.stuid = s.stuid
Left Join courses c On c.courseno = s.courseno
Group by st.stuid

看上面的语句可以看出,我们是在知道固定的几门课程之后,可以使用

MAX(CASE c.coursenm WHEN "线性代数" THEN ifnull(s.scores,0) ELSE 0 END ) "线性代数",

这样的语句来实现行转列

 

但课程不仅仅这几门,如果用上面的语句去写,第一要确定有多少课程,这么多课程的课程名要再拿出来,那样的话写一个查询语句下来,可是要写很多了。


动态行转列

如何进行动态行转列呢?首先我们要动态获取这样的语句

MAX(CASE c.coursenm WHEN "大学语文" THEN s.scores ELSE 0 END ) "大学语文",
MAX(CASE c.coursenm WHEN "线性代数" THEN ifnull(s.scores,0) ELSE 0 END ) "线性代数", 
MAX(CASE c.coursenm WHEN "离散数学" THEN ifnull(s.scores,0) ELSE 0 END ) "离散数学"

而不是像上面那样一句句写出来,这里就要用到SQL语句拼接了。具体就是下面的语句

SELECT
	GROUP_CONCAT( DISTINCT CONCAT( "MAX(IF(c.coursenm = """, c.coursenm, """, s.scores, 0)) AS """, c.coursenm, """" ) ) 
FROM
	courses c;

 

上面就是进行行转列查询要用的语句,那样就不用知道多少课程和这些课程的名字,只要这样几行代码便可以得到动态的列了。

动态的列是拿到了,那如何再结合SQL语句进行查询得到结果呢?

这里要说明一点,因为用到了拼接函数,如果像上面的查询语句,只是把那几行语句替换掉,也就是下面这样

Select st.stuid, st.stunm, 
(
 SELECT
 GROUP_CONCAT(DISTINCT
 CONCAT(
 "MAX(IF(c.coursenm = """,
 c.coursenm,
 """, s.scores, NULL)) AS ",
 c.coursenm
 )
 )
 FROM courses c
)
From Student st
Left Join score s On st.stuid = s.stuid
Left Join courses c On c.courseno = s.courseno
Group by st.stuid;

然而得到的结果却是这样的

 

最终结果如下:

像普通的那些语句那样进行声明,将语句拼接完整之后,再执行

--动态行转列
SET @SQL = NULL;
SELECT
	GROUP_CONCAT( DISTINCT CONCAT( "MAX(IF(c.coursenm = """, c.coursenm, """, s.scores, 0)) AS """, c.coursenm, """" ) ) INTO @SQL 
FROM
	courses c;
 
SET @SQL = CONCAT( "Select st.stuid, st.stunm, ", @SQL, " From Student st 
	Left Join score s On st.stuid = s.stuid
	Left Join courses c On c.courseno = s.courseno
Group by st.stuid" );
PREPARE stmt 
FROM
	@SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

 

这样就实现了动态行转列的目的了。而且我们不用知道多少课程,也无需把这些课程名一一列出来。当然这个语句拼接中的查询可以加入条件查询。


存储过程–动态行转列

用存储过程的好处是,方便我们调用,相当于一个函数,其他可能也是类似的查询不需再重复写代码,直接调存储过程就好,还能随心所欲的加上if条件判断

创建存储过程的语句我就不多写了,这里把上面的查询语句直接放到创建存储过程的begin和end直接就可以了,如下:

DELIMITER && 
drop procedure if exists SP_QueryData;
Create Procedure SP_QueryData(IN stuid varchar(16))
READS SQL DATA 
BEGIN
 
SET @sql = NULL;
SET @stuid = NULL;
SELECT
 GROUP_CONCAT(DISTINCT
 CONCAT(
 "MAX(IF(c.coursenm = """,
 c.coursenm,
 """, s.scores, 0)) AS """,
 c.coursenm, """
 )
 ) INTO @sql
FROM courses c;
 
SET @sql = CONCAT("Select st.stuid, st.stunm, ", @sql, 
 " From Student st 
 Left Join score s On st.stuid = s.stuid
 Left Join courses c On c.courseno = s.courseno");
 
IF stuid is not null and stuid <> "" then
SET @stuid = stuid;
SET @sql = CONCAT(@sql, " Where st.stuid = "", @stuid, """);
END IF; 
 
SET @sql = CONCAT(@sql, " Group by st.stuid");
 
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
 
END && 
DELIMITER ;

 

调用存储过程:

CALL `SP_QueryData`("1001");

得到如下结果

 

 

也可以直接传个空串过去

CALL `SP_QueryData`("");

同样得到我们想要的结果

 


总结

以上就是mysql数据库行转列实现的过程中的内容,耐心看完并认真研究的话,这个内容对你的行转列还是有很大帮助的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/11145.html

(0)
上一篇 2022-12-15 21:00
下一篇 2022-12-15

相关推荐

  • Python 强制类型转化教程

    Python 强制类型转化教程Python作为一门高级语言,其默认情况下都是采用动态类型语言进行编程的。然而,有时候你可能需要在程序中对数据类型进行强制转换。比如说你需要在字符串和整数之间进行加减操作,或者将一个整数转化为一个浮点数。本文将介绍Python的强制类型转化,也称为类型转换。读完本文,你将能够在Python程序中对数据类型进行强制转换,从而更好地控制程序的输出。

    2024-05-04
    55
  • python中英文时间转换的简单介绍

    python中英文时间转换的简单介绍python编程用datetime方法进行时间转换,代码如下:

    2023-11-01
    118
  • Handler_read_*的总结「终于解决」

    Handler_read_*的总结「终于解决」优化SQL,只懂执行计划?不行滴!

    2023-04-17
    130
  • Python dictadd函数详解

    Python dictadd函数详解在日常的python开发中,字典(dict)是十分常用的数据类型。而在实际开发中,我们往往需要对字典进行添加元素的操作。在此背景下,strongPython dictadd函数详解/strong应运而生。在本篇文章中,我们将会从多个方面来对该函数进行详细介绍。

    2024-08-24
    21
  • 谈谈数据库sql编写

    谈谈数据库sql编写本文主要给初学者关于关系数库的一个浮光掠影式的介绍,如果想深入理解,必须对于下文提到的每个内容单独深入学习! it-information technology的简称,中文是信息机技术,信息其实就是数

    2022-12-28
    147
  • [安装] 创建asmlib 磁盘失败

    [安装] 创建asmlib 磁盘失败[root@db01 mapper]# oracleasm createdisk vot01 /dev/mapper/votdsk01 oracleasm module not loaded or …

    2022-12-27
    141
  • 【呕心总结】Python如何与mysql实现交互及常用sql语句

    【呕心总结】Python如何与mysql实现交互及常用sql语句这篇笔记,整理实战中最常用到的 mysql 语句,同时也将涉及到如何在python3中与 mysql 实现数据交换。 关于工具/库,特别说明下: 1、我安装了 mysql ,并直接采用管理员身份运行…

    2023-02-21
    132
  • windows查看mysql状态_MySQL查看表命令

    windows查看mysql状态_MySQL查看表命令memroy_global_total 记录 server总共分配出去的内存 host_summary,查看连接到mysql的主机信息 字段名 意义 host 从哪个服务器上连过来。如果是NULL,…

    2023-02-01
    138

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注