首页 > 数据库 >mysql行转列小技巧

mysql行转列小技巧

时间:2023-06-06 19:35:37浏览次数:50  
标签:Insert 技巧 courseno Into scores 转列 Values mysql stuid


下面是具体的测试过程:

数据表结构:

采用经典的学生,课程,成绩表:

CREATE TABLE `student` (
    `stuid` VARCHAR(16) NOT NULL COMMENT '学号',
    `stunm` VARCHAR(20) NOT NULL COMMENT '学生姓名',
    PRIMARY KEY (`stuid`)
)
CREATE TABLE `courses` (
    `courseno` VARCHAR(20) NOT NULL,
    `coursenm` VARCHAR(100) NOT NULL,
    PRIMARY KEY (`courseno`)
)
COMMENT='课程表'
CREATE TABLE `score` (
    `stuid` VARCHAR(16) NOT NULL,
    `courseno` VARCHAR(20) NOT NULL,
    `scores` FLOAT NULL DEFAULT NULL,
    PRIMARY KEY (`stuid`, `courseno`)
)

数据准备:

/*学生表数据*/
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);



方法一:

静态的行转列:缺点是要知道固定的列,方可使用:

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

执行结果如下:

mysql行转列小技巧_sql


方法二:动态的行转列

在这里要借住存储过程,代码段如下:


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


mysql> DELIMITER &&
mysql> 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 &&
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected (0.00 sec)



执行结果:

mysql行转列小技巧_离散数学_02



分部解释一下:

1,首先要获得动态的组合语句:

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

执行结果:

mysql行转列小技巧_sql_03



2,因为是拼接语句,后面即时加上where语句,得到的结果也不是我们想要的,正在这里要像普通的语句那样,进行声明,将语句拼接完整之后,在执行:

代码:

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;

执行结果:

mysql行转列小技巧_sql_04



这样在sql中执行,可得到结果。

注意几个地方:

1. if条件的使用,就是直接用,不需要括号。

详细内容请参考原文,写的比较详细,我这里抽取骨干,拿来直接测试一下。

标签:Insert,技巧,courseno,Into,scores,转列,Values,mysql,stuid
From: https://blog.51cto.com/u_16152230/6427032

相关文章

  • mysql select into outfile 语法 乱码问题
    一个常见的问题,mysql导出csv格式的语法,已经乱码问题:由于数据库一般默认的是UTF-8格式的字符集,而execl默认的是gbk格式的字符集,这里有两种方法解决乱码:方法一:先转出.txt格式的文件,然后选择用excel打开时,提示选择哪种编码打开,选择gbk即可select*frommobile_order_regionwhere......
  • Mysql5.6.10源码安装步骤
    Mysql5.6.10源码安装步骤//MySQL5.6.10源码安装步骤: 系统环境:CentOS5.6 MySQL版本:mysql-5.6.10.tar.gz 安装路径:/usr/local/mysql 数据目录:/data/mysql/data CentOS5.6下MySQL5.6源码安装 Linux操作系统:CentOS5.61:下载:当前mysql版本到了5.6.10 下载地址:ht......
  • mysql 多值检索 find_in_set()函数
    问题描述:有一个字段type类型,存储的值为:1,2,3,4,等这样的,要检索出里面全部含有某一个类型的值,列如3想要的结果如下:如何实现。。下面是具体的示例:+-----+-----------+|fid|type|+-----+-----------+|1|1,2,3,4,5||4|2,3,4,5|+-----+-----------+2rowsins......
  • MySQL server version for the right syntax to use near 'OPTION SQL_SELECT_LIMIT=D
    hive删除表时报错如下:hive>droptableaaa;FAILED:ExecutionError,returncode1fromorg.apache.hadoop.hive.ql.exec.DDLTask.MetaException(message:javax.jdo.JDODataStoreException:YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyou......
  • Online DDL in MySQL 5.6
    OnlineDDLinMySQL5.6转载一篇姜老师的:在线DDL操作(OnlineDDL)是MySQL5.6中最为另人激动的改进功能。从历史上看,若我没记错MySQL在2007年就完成了在线索引接口的设计。而MySQLNDBCluster、TokuDB都早在5.1版本中就支持在线索引添加,然而直到MySQL5.6用户才能享受到该功能(虽......
  • MYSQL联合查询
       ......
  • MYSQL查询
         子查询   分页查询 ......
  • MYSQL分页查询
          ......
  • mysql数据库的锁-select for update
    乐观锁与悲观锁乐观锁和悲观锁只是两个加锁的思路,其实现方式多种多样。以下举几个在mysql数据库中的例子。  对于一次的数据修改,我们可以大概将其分为三步:获取数据修改数据提交修改乐观锁假设A、B两个角色对数据进行修改:乐观锁对数据保持一个乐观态度(大概率......
  • Mysql Workbench的CSV数据导入
    首先新建一个数据库和要从.csv导入数据的表,注意数据格式的选取。然后将csv文件用NOTEPAD++打开,将文件格式转换为UTF8.转化完成即可关闭。在MysqlWorkbench中想要导入数据的表,右键选取TableDataImportWizard进入数据导入向导,在文件路径中找到csv文件,下一步。选择Useex......