Mysql之行与列的多种转换实现方式

 更新时间:2026年03月25日 10:00:35   作者:雷神乐乐  
这篇文章主要介绍了Mysql之行与列的多种转换实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Mysql行与列的多种转换

首先准备一张表

CREATE TABLE CJ
(
    Name    varchar(32),
    Subject varchar(32),
    Result  int(10)
);

# 插入数据
insert into cj
values ('张三', '语文', 80),
       ('张三', '数学', 90),
       ('张三', '物理', 85),
       ('李四', '语文', 85),
       ('李四', '数学', 92),
       ('李四', '物理', 82);

一、行转列

第一步,先将科目分类好:

SELECT Name,
       CASE WHEN Subject='语文' THEN Result ELSE 0 END AS 语文,
       CASE WHEN Subject='数学' THEN Result ELSE 0 END AS 数学,
       CASE WHEN Subject='物理' THEN Result ELSE 0 END AS 物理
FROM cj;

第二步:将上面的结果看做一张表,从表中找出每一个新字段的最大值,对Name进行分组

SELECT T.Name,
       MAX(T.语文) 语文,
       MAX(T.数学) 数学,
       MAX(T.物理) 物理
FROM (SELECT Name,
       CASE WHEN Subject='语文' THEN Result ELSE 0 END AS 语文,
       CASE WHEN Subject='数学' THEN Result ELSE 0 END AS 数学,
       CASE WHEN Subject='物理' THEN Result ELSE 0 END AS 物理
FROM cj) T
GROUP BY T.Name;

案例二:查询用户安装APP的情况

create table app
(
    id  int,
    app varchar(32)
);

insert into app(id, app)
VALUES (1, '微信'),
       (2, '快手'),
       (3, 'QQ'),
       (4, '抖音'),
       (5, '美团'),
       (6, '饿了么'),
       (7, '支付宝'),
       (8, '拼多多'),
       (9, '高德地图');

CREATE TABLE app_install
(
    uid int,
    app varchar(32)
);

insert into app_install(uid, app)
VALUES (1, '微信'),
       (1, '美团'),
       (2, '支付宝'),
       (2, '高德地图'),
       (3, '拼多多');

select uid,
       case when app = '微信' then 1 else 0 end as 'wx',
       case when app = '快手' then 1 else 0 end as 'ks',
       case when app = 'QQ' then 1 else 0 end as 'qq',
       case when app = '抖音' then 1 else 0 end as 'dy',
       case when app = '美团' then 1 else 0 end as 'mt',
       case when app = '饿了么' then 1 else 0 end as 'elm',
       case when app = '支付宝' then 1 else 0 end as 'zfb',
       case when app = '拼多多' then 1 else 0 end as 'pdd',
       case when app = '高德地图' then 1 else 0 end as 'gd'
from app_install;

select t.uid,
       case when max(t.wx) then '已安装' else '未安装' end as 'wx',
       case when max(t.ks) then '已安装' else '未安装' end as 'ks',
       case when max(t.qq) then '已安装' else '未安装' end as 'qq',
       case when max(t.dy) then '已安装' else '未安装' end as 'dy',
       case when max(t.mt) then '已安装' else '未安装' end as 'mt',
       case when max(t.elm) then '已安装' else '未安装' end as 'eml',
       case when max(t.zfb) then '已安装' else '未安装' end as 'zfb',
       case when max(t.pdd) then '已安装' else '未安装' end as 'pdd',
       case when max(t.gd) then '已安装' else '未安装' end as 'gd'
from  (select uid,
       case when app = '微信' then 1 else 0 end as 'wx',
       case when app = '快手' then 1 else 0 end as 'ks',
       case when app = 'QQ' then 1 else 0 end as 'qq',
       case when app = '抖音' then 1 else 0 end as 'dy',
       case when app = '美团' then 1 else 0 end as 'mt',
       case when app = '饿了么' then 1 else 0 end as 'elm',
       case when app = '支付宝' then 1 else 0 end as 'zfb',
       case when app = '拼多多' then 1 else 0 end as 'pdd',
       case when app = '高德地图' then 1 else 0 end as 'gd'
from app_install) t
group by t.uid;

连表比子查询要好  

二、列转行

建表

CREATE TABLE CJ2
(
    Name varchar(32),
    `语文` int(10),
    `数学` int(10),
    `物理` int(10)
);


# 插入数据
insert into cj2 values ('张三',80,90,90),('李四',85,92,92);

原表:

SELECT Name,'语文' cource,语文 result
FROM cj2
union all
SELECT Name,'数学' cource,数学 result
FROM cj2
union all
SELECT Name,'物理' cource,物理 result
FROM cj2;

# 查询后按照结果排序
SELECT *
FROM (SELECT Name,'语文' cource,语文 result
FROM cj2
union all
SELECT Name,'数学' cource,数学 result
FROM cj2
union all
SELECT Name,'物理' cource,物理 result
FROM cj2) T
ORDER BY T.Name;

三、多列转一行

将科目与分数排在一列

SELECT Name,GROUP_CONCAT(Subject,':',Result) 成绩
FROM cj
group by Name;

 

四、一行转多列

将上表还原

# 建表
CREATE TABLE CJ3
(
    Name varchar(32),
    `成绩` varchar(50)
);

# 插入数据
insert into cj3
values ('张三', '语文:80,数学:90,物理:85'),
       ('李四', '语文:85,数学:92,物理:82');

SELECT Name,
       CASE
           WHEN LOCATE('语文', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '语文:', -1), ',', 1)
           else 0 end as 语文,
       CASE
           WHEN LOCATE('数学', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '数学:', -1), ',', 1)
           else 0 end as 数学,
       CASE
           WHEN LOCATE('物理', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '物理:', -1), ',', 1)
           else 0 end as 物理
from cj3;

SELECT T1.Name, '语文' Cource, T1.语文 result
FROM (SELECT Name,
             CASE
                 WHEN LOCATE('语文', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '语文:', -1), ',', 1)
                 else 0 end as 语文
      from cj3) T1
union all
SELECT T2.Name, '数学' Cource, T2.数学 result
FROM (SELECT Name,
             CASE
                 WHEN LOCATE('数学', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '数学:', -1), ',', 1)
                 else 0 end as 数学
      from cj3) T2
union all
SELECT T3.Name, '物理' Cource, T3.物理 result
FROM (SELECT Name,
             CASE
                 WHEN LOCATE('物理', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '物理:', -1), ',', 1)
                 else 0 end as 物理
      from cj3) T3;

SELECT *
FROM (SELECT T1.Name, '语文' Cource, T1.语文 result
FROM (SELECT Name,
             CASE
                 WHEN LOCATE('语文', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '语文:', -1), ',', 1)
                 else 0 end as 语文
      from cj3) T1
union all
SELECT T2.Name, '数学' Cource, T2.数学 result
FROM (SELECT Name,
             CASE
                 WHEN LOCATE('数学', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '数学:', -1), ',', 1)
                 else 0 end as 数学
      from cj3) T2
union all
SELECT T3.Name, '物理' Cource, T3.物理 result
FROM (SELECT Name,
             CASE
                 WHEN LOCATE('物理', 成绩) > 0 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(成绩, '物理:', -1), ',', 1)
                 else 0 end as 物理
      from cj3) T3) T
ORDER BY T.Name;

五、行转列的其他案例

准备一张result表

行转列

# 查询1000号学生四门科目的成绩
select StudentNo,
       case when SubjectNo = 1 then StudentResult else 0 end as 高等数学1,
       case when SubjectNo = 2 then StudentResult else 0 end as 高等数学2,
       case when SubjectNo = 3 then StudentResult else 0 end as java编程,
       case when SubjectNo = 4 then StudentResult else 0 end as hadoop理论
from result
where StudentNo = 1000;

# 简化
select StudentNo, MAX(高等数学1) math1, MAX(高等数学2) math2, MAX(java编程) java, MAX(hadoop理论) hadoop
from (select StudentNo,
             case when SubjectNo = 1 then StudentResult else 0 end as 高等数学1,
             case when SubjectNo = 2 then StudentResult else 0 end as 高等数学2,
             case when SubjectNo = 3 then StudentResult else 0 end as java编程,
             case when SubjectNo = 4 then StudentResult else 0 end as hadoop理论
      from result
      where StudentNo = 1000) T;

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • mysql命令导出表结构和数据的操作方法

    mysql命令导出表结构和数据的操作方法

    在日常使用中,我们经常需要对数据库进行备份和复制,因此必须了解如何导出表结构和表数据,以下是使用MySQL命令导出表结构和表数据的方法,感兴趣的朋友一起看看吧
    2023-11-11
  • MySQL数据库数据视图

    MySQL数据库数据视图

    这篇文章主要介绍了MySQL数据库数据视图,视图是原始数据库数据的一种变换,是查看表中数据的另外一种方式,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • 浅谈MySQL查询出的值为NULL和N/A和空值的区别

    浅谈MySQL查询出的值为NULL和N/A和空值的区别

    本文主要介绍了浅谈MySQL查询出的值为NULL和N/A和空值的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • Centos下安装多个mysql数据库的配置实例详解

    Centos下安装多个mysql数据库的配置实例详解

    在实际的开发和运维场景中,有时我们需要在同一台服务器上运行多个MySQL数据库实例,本文将详细介绍如何在CentOS系统中安装并配置多个MySQL数据库实例,希望对大家有所帮助
    2025-04-04
  • MySQL禁用InnoDB引擎的方法

    MySQL禁用InnoDB引擎的方法

    这篇文章主要介绍了MySQL禁用InnoDB引擎的方法,针对的Mysql版本是5.5和5.6,使用了两种不同的配置文件,需要的朋友可以参考下
    2014-05-05
  • MySQL8.0 如何快速加列

    MySQL8.0 如何快速加列

    这篇文章主要介绍了MySQL8.0 如何快速加列,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2020-09-09
  • MySQL 批量插入的原理和实战方法(快速提升大数据导入效率)

    MySQL 批量插入的原理和实战方法(快速提升大数据导入效率)

    在日常开发中,我们经常需要将大量数据批量插入到 MySQL 数据库中,本文将介绍批量插入的原理、实现方法,并结合 Python 和 PyMySQL 库提供详细的实战示例,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • MySQL最左匹配原则深入分析

    MySQL最左匹配原则深入分析

    首先回顾一下什么是最左匹配(也有称之为最左前缀)?顾名思义:最左优先,以最左边的为起点任何连续的索引都能匹配上。同时遇到范围查询(>、<、between、like)就会停止匹配
    2022-11-11
  • MySQL定期分析检查与优化表的方法小结

    MySQL定期分析检查与优化表的方法小结

    听DBA的人说,相比oracle,MySQL就是一个玩具级别的数据库,在网易门户中,DBA基本很少去管理到MySQL的东西,所以我们产品使用到的MySQL的一些配置和优化还是需要我们开发人员自己动手,下面就简单介绍一下实用的定期优化方法
    2014-06-06
  • Mysql主从同步的实现原理

    Mysql主从同步的实现原理

    这篇文章主要介绍了Mysql主从同步的实现原理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03

最新评论