【SQL应知应会】行列转换(三)• Oracle版

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 【SQL应知应会】行列转换(三)• Oracle版

前言

前面的两篇文章【SQL应知应会】行列转换(一)• MySQL版和【SQL应知应会】行列转换(二)• MySQL版详细的讲述了MySQL的行列转换,而今天这篇文章,讲的是Oracle中的行列转换,其中有与MySQL共同的方法,也有Oracle专用的方法,希望对大家在学习上能有所帮助。


1.数据准备

1.1知识点补充

create table table_grade(id int,user_name varchar(20),course varchar(10),score decimal(5,2));


oracle 中没有int,有integer类型,不过兼容 oracle没有double

oracle没有varchar类型,有varchar2,不过使用varchar也可以建

decimal有,但是建进去会变成number,number既支持整数又支持小数,最大可以设置到38位


drop table table_grade purge;


oracle 删除的时候要加purge,因为oracle有回收站机制,不加purge的话会将删除的东西放在回收站中,这样的话,之后还需要进行一个recyclebin的操作


PURGE RECYCLEBIN; -- 清空某一用户的所有表空间下的对象


1.2 知识点应用

create table table_grade (id number(38),user_name varchar(20),course varchar(10),score decimal(5));


insert into table_grade values('1','张龙','语文','78');
insert into table_grade values('2','张龙','数学','95');
insert into table_grade values('3','张龙','英语','81');
insert into table_grade values('4','赵虎','语文','97');
insert into table_grade values('5','赵虎','数学','78');
insert into table_grade values('6','赵虎','英语','91');
insert into table_grade values('7','王五','语文','81');
insert into table_grade values('8','王五','数学','55');
insert into table_grade values('9','王五','英语','75');
insert into table_grade values('10','马六','语文','87');
insert into table_grade values('11','马六','数学','65');
insert into table_grade values('12','马六','英语','75');
commit; -- 插入数据后,需要进行一个提交


2.行转列

2.1通用的行转列(Mysql和Oracle都能用) ——> case when

select id "学生ID",    -- oracle中单引号被识别为字段里的一个值,所以别名使用双引号 -- 我的猜想:好像加as就可以用单引号了--> 没验证成功
    (select max(user_name) from table_grade where id = t.id) user_name,
    max(case when course = '语文' then score end) "语文",
    max(case when course = '数学' then score end) "数学",
    max(case when course = '英语' then score end) "英语"
from table_grade
group by id;


2.2 私有方法的行转列(Oracle用) ——> decode()

select id "学生ID",
    (select max(user_name) from table_grade where id = t.id) user_name,
    max(decode(course,'语文',score,'')) "语文",
    max(decode(course,'数学',score,'')) "数学",
    max(decode(course,'英语',score,'')) "英语"
from table_grade t
group by id order by 1
-- decode(字段或字段的运算,值1,值2,值3)
   -- 当字段或字段的运算的值等于值1时,该函数返回值2,否则返回值3
  -- 当然值1,值2,值3也可以是表达式,这个函数使得某些sql语句简单了许多


2.3 终极方法(Oracle用) ——> 透视表函数pivot()

2.3.1理论

select * from table_name
pivot(max(column_name)   -- 行转列后的列的值value,聚合函数是必须要有的
  for column_name in (value_1,value_2,value_3)) -- 需要行转列的列及其对应的属性1/2/3


2.3.2 应用

select * from table_grade 
pivot(max(score)   -- 此处max()改成min/sum/avg是一样的,因为此时的table_grade表中,一个学生每门课就有一个成绩
  for course in ('语文' 语文,'数学' 数学,'英语' 英语))  -- 先写值value,因为course是字符串,所以加单引号   后面是别名


2.3.3美化

select user_name,语文,数学,英语 from table_grade 
pivot(max(score)
  for course in ('语文' 语文,'数学' 数学,'英语' 英语)) 
order by user_name


3.列转行

3.1with as

with as 是oracle特有写法,可以将as中的查询当做一个表来使用

with table_grade_wide 
as (select user_name "姓名",
      max(case when course = '语文' then score end) "语文",
      max(case when course = '数学' then score end) "数学",
      max(case when course = '英语' then score end) "英语"
   from table_grade t
   group by user_name)


然后就可以当做一个表使用了

select * from table_grade_wide


3.2进行一个列转行的操作(这是通用方法) ——> union

- select * from (
    select 姓名,'语文' course,语文 score from table_grade_wide
    union  -- 如果此处使用union all 的话,和union是没有区别的,前一句是赋值语文,下一句是赋值数学,二者union不会去重,相当于产生一个course字段分别是语文和数学,所以二者去重是不会消掉数据的
    select 姓名,'数学' ,数学 from table_grade_wide
    union
    select 姓名,'英语' ,英语 from table_grade_wide) -- a -- 这里这个虚拟的表就可以当做真实的表来使用了,所以就不需要给它别名了 -- ?为什么可以当做真实的表用了?这是oracle的原因吗
  -- where score id not null   -- 这句如果原来表中有的学生就没有其中一门课的数据,比如王五和马六只有两门课的数据,那就可以通过这句话来解决table_grade_wide表中王五和马六对应的没有的那门课的null;如果表中的学生有课但是成绩是null,那就没有必要使用这句代码,不然就把学生拥有的那门课删掉了,相当于造成了数据丢失
  order by 姓名


3.3 列转行终极方法(Oracle用) ——> unpivot()

with table_grade_wide 
as (select user_name "姓名",
      max(case when course = '语文' then score end) "语文",
      max(case when course = '数学' then score end) "数学",
      max(case when course = '英语' then score end) "英语"
   from table_grade t
   group by user_name)
select 姓名 user_name,course,score from table_grade_wide unpivot(score for course in (语文,数学,英语))


3.4 一个学生一门课有多次成绩的时候

数据准备

代码

# 求一个学生每门课程近三次考试中最高的成绩
SELECT t1.s_id,t1.c_id, MAX(t1.score) AS best_score
FROM (
  SELECT s_id,c_id, score, 
         ROW_NUMBER() OVER (PARTITION BY s_id,c_id ORDER BY exam_date DESC) AS rn
  FROM sc
) t1
WHERE t1.rn <= 3
GROUP BY t1.s_id,t1.c_id

小结

好了,Oracle的行列转换到这里就要告一段落了,相信大家通过前两篇文章【SQL应知应会】行列转换(一)• MySQL版和【SQL应知应会】行列转换(二)• MySQL版,应该对MySQL的行列转换有了了解,并且通过今天这篇文章对Oracle的行列转换也进行了学习,应该对MySQL和Oracle的行列转换的相同以及不同之处有所了解,那么数据库的行列转换这一模块我们就告一段落了,接下来还会给大家带来其他方面的知识讲解,希望能对大家有所帮助


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
1月前
|
SQL Oracle 关系型数据库
Oracle数据库创建表空间和索引的SQL语法示例
以上SQL语法提供了一种标准方式去组织Oracle数据库内部结构,并且通过合理使用可以显著改善查询速度及整体性能。需要注意,在实际应用过程当中应该根据具体业务需求、系统资源状况以及预期目标去合理规划并调整参数设置以达到最佳效果。
98 8
|
3月前
|
SQL
SQL 如何将表中行列互换
本文介绍了在 SQL 中使用 PIVOT 和 UNPIVOT 实现行列互换的方法。通过实例展示了如何将学生各科成绩由行转为列,并强调使用 PIVOT 时需隐藏无关列以避免重复行。同时说明了数据类型转换及非数字数据的处理方式。
|
6月前
|
SQL Oracle 关系型数据库
解决大小写、保留字与特殊字符问题!Oracle双引号在SQL中的特殊应用
在Oracle数据库开发中,双引号的使用是一个重要但易被忽视的细节。本文全面解析了双引号在SQL中的特殊应用场景,包括解决标识符与保留字冲突、强制保留大小写、支持特殊字符和数字开头标识符等。同时提供了最佳实践建议,帮助开发者规避常见错误,提高代码可维护性和效率。
219 6
|
7月前
|
SQL Oracle 关系型数据库
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
|
7月前
|
SQL Oracle 关系型数据库
【YashanDB知识库】yashandb执行包含带oracle dblink表的sql时性能差
【YashanDB知识库】yashandb执行包含带oracle dblink表的sql时性能差
|
7月前
|
SQL Oracle 关系型数据库
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
本文来自YashanDB官网,介绍如何处理Oracle客户端sql*plus中使用@@调用同级目录SQL脚本的场景。崖山数据库23.2.x.100已支持@@用法,但旧版本可通过Python脚本批量重写SQL文件,将@@替换为绝对路径。文章通过Oracle示例展示了具体用法,并提供Python脚本实现自动化处理,最后调整批处理脚本以适配YashanDB运行环境。
|
9月前
|
SQL Oracle 关系型数据库
如何在 Oracle 中配置和使用 SQL Profiles 来优化查询性能?
在 Oracle 数据库中,SQL Profiles 是优化查询性能的工具,通过提供额外统计信息帮助生成更有效的执行计划。配置和使用步骤包括:1. 启用自动 SQL 调优;2. 手动创建 SQL Profile,涉及收集、执行调优任务、查看报告及应用建议;3. 验证效果;4. 使用 `DBA_SQL_PROFILES` 视图管理 Profile。
|
SQL 关系型数据库 Oracle
ORACLE SQL优化之ORA-03150&ORA-02055&ORA-02063
                                                                                                             >   
4995 0
|
SQL Oracle 关系型数据库
Oracle SQL优化之多表连接
Oracle SQL优化之多表连接
729 0
Oracle SQL优化之多表连接
|
SQL 存储 Oracle
Oracle数据库 | SQL语句执行计划、语句跟踪与优化实例
Oracle数据库 | SQL语句执行计划、语句跟踪与优化实例
449 0

热门文章

最新文章

推荐镜像

更多