SQL 行转列+窗口函数的实例
时间:2022-07-22
本文章向大家介绍SQL 行转列+窗口函数的实例,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
今天继续和大家分享 HackerRank 上的 SQL 编程挑战的解题思路,这一次的题目叫做“Occupations”,属于中等难度级别,答案提交的成功率在 90% 左右。
问题描述
有一个职业表(OCCUPATIONS ),它有两个字段:Name、Occupation。其中,Occupation 的值只有四种:Doctor、Professor、Singer 和 Actor 。
OCCUPATIONS 表的表结构及数据如下:
Column |
Type |
---|---|
Name |
String |
Occupation |
String |
OCCUPATIONS 的表结构
Name |
Occupation |
---|---|
Samantha |
Doctor |
Julia |
Actor |
Maria |
Actor |
Meera |
Singer |
Ashley |
Professor |
Ketty |
Professor |
Christeen |
Professor |
Jane |
Actor |
Jenny |
Doctor |
Priya |
Singer |
OCCUPATIONS 的表数据
要求:
- 将数据按照 Doctor、Professor、Singer 、Actor 的顺序分成四列输出;
- 每一列的数据从上到下按姓名的字母顺序升序排序;
- 人员不足的职位列上用 NULL 填充。
输出结果:
Jenny Ashley Meera Jane
Samantha Christeen Priya Julia
NULL Ketty NULL Maria
解决方案
一般遇到“将一列中的所有唯一值作为新的列名输出”这种需求,我们首先想到的就应该是行转列,我之前写过一篇介绍SQL 行转列的通用实现的文章,感兴趣的朋友点进来看看。
做行转列时分组的依据是什么呢?即依据哪个字段分组。答案是依据每个职位中姓名的排序序号作为分组条件,而每个职位里面姓名的出现的序号可通过窗口函数求得。
先来看看对职业为 “Actor” 和 “Doctor” 的数据做组内排序。
SELECT
occupation as p,
row_number () over (
PARTITION BY occupation
ORDER BY name
) AS rn,
name
FROM
OCCUPATIONS
WHERE
occupation IN ('Actor','Doctor')
排序的结果:
p rn name
------ -- --------
Actor 1 Eve
Actor 2 Jennifer
Actor 3 Ketty
Actor 4 Samantha
Doctor 1 Aamina
Doctor 2 Julia
Doctor 3 Priya
最后,我们把窗口函数和行转列结合起来,就可以实现题目所要求的输出。
WITH t AS
(SELECT
occupation,
row_number () over (
PARTITION BY occupation
ORDER BY NAME
) AS rn,
NAME
FROM
OCCUPATIONS)
SELECT
MAX(
IF(occupation = 'Doctor', NAME, NULL)
) AS Doctor,
MAX(
IF(
occupation = 'Professor',
NAME,
NULL
)
) AS Professor,
MAX(
IF(occupation = 'Singer', NAME, NULL)
) AS Singer,
MAX(IF(occupation = 'Actor', NAME, NULL)) AS Actor
FROM
t
GROUP BY rn
如果你的 MySQL 数据库的版本在 8.0 之前,那么可以用用户变量替代窗口函数实现组内排序的功能。
SELECT
MAX(
IF(occupation = 'Doctor', NAME, NULL)
) AS Doctor,
MAX(
IF(
occupation = 'Professor',
NAME,
NULL
)
) AS Professor,
MAX(
IF(occupation = 'Singer', NAME, NULL)
) AS Singer,
MAX(IF(occupation = 'Actor', NAME, NULL)) AS Actor
FROM
(SELECT
NAME,
occupation,
@rn := IF(@oc = occupation, @rn + 1, 1) AS seq,
@oc := occupation
FROM
occupations a,
(SELECT
@rn := 0,
@oc := NULL) b
ORDER BY occupation,name
) t
GROUP BY seq
- 分分钟搭建MySQL Group Replication测试环境(r11笔记第82天)
- MySQL 5.7 Group Replication错误总结(r11笔记第84天)
- 空结构体struct{}解析
- 动态创建MySQL Group Replication的节点(r11笔记第84天)
- sysbench压测小记(r11笔记第99天)
- WordPress启用memcached动态缓存以及报错解决
- 升级CentOS6.5内核,开启Nginx的fastopen和reuseport特性
- Nginx网站使用CDN之后禁止用户真实IP访问的方法
- 相差数十倍的SQL性能分析(r11笔记第98天)
- shell脚本实现整站缓存和预缓存,进一步提升网站整体加载速度
- Oracle中的PGA监控报警分析(r11笔记第96天)
- MySQL错误修复记录:Table xx is marked as crashed and should be repaired
- WordPress百度自动推送JS优化,规避错误、重复推送问题
- Oracle 12c中DBCA搭建备库体验(r11笔记第92天)
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- 设计模式实战-状态模式,让代码更清爽简洁
- 改善深层神经网络——吴恩达深度学习课程笔记(二)
- Spring Boot 监听 Redis Key 失效事件实现定时任务,超时订单自动关闭绝佳实现
- TensorFlow的核心概念:张量和计算图
- 四连问:API 接口应该如何设计?如何保证安全?如何签名?如何防重?
- TensorFlow基础:创建计算图
- TensorFlow基础:常量
- 如何在Python中优雅地使用进度条?
- 绝了!这款工具让SpringBoot不再需要Controller、Service、DAO、Mapper!
- 「数据仓库架构」数据仓库的三种模式建模技术
- 设计模式实战-空对象模式,你肯定不知道,但是项目中会常用到到
- Go 开发十种常犯错误
- SpringBoot缓存应用实践
- 为什么应该使用 Go module proxy
- 谁能想到,我给技术总监“上了一课”