关于优雅的使用SQL多行转多列的记录(doris)

文章目录

  • 应用需求场景
  • 记录过程
      • [1. 准备数据](#1. 准备数据)
      • [2. 给数据根据姓名分组,加上序号.](#2. 给数据根据姓名分组,加上序号.)
      • [3. 根据name分组成map结构](#3. 根据name分组成map结构)
      • [4. 拆分map](#4. 拆分map)

应用需求场景

准备的数据是这样的:

需要将每个人的成绩显示在一行上,需要的结果如下,但是我的情况是课程有非常多,但不是每个课程都存在。我只想把这个人学习的3个课程列出来,所以这类有个问题,就是每个同学的课程不一定是语文、数学、英语,但是最大不多于3门课。

最终的结果如下:

记录过程

1. 准备数据

sql 复制代码
with tmp_a as (
	select 'a' name,'语文' clazz, 80 as score
	union all
	select 'a' name,'高数' clazz, 85 as score
	union all
	select 'a' name,'英语' clazz, 20 as score
	union all
	select 'b' name,'微积分' clazz, 70 as score
	union all
	select 'b' name,'数学' clazz, 75 as score
	union all
	select 'b' name,'现代' clazz, 71 as score
	union all
	select 'c' name,'物理' clazz, 70 as score
	union all
	select 'c' name,'音乐' clazz, 75 as score
	union all
	select 'c' name,'体育' clazz, 71 as score
)
select * from tmp_a;

2. 给数据根据姓名分组,加上序号.

sql 复制代码
with tmp_a as (
	select 'a' name,'语文' clazz, 80 as score
	union all
	select 'a' name,'高数' clazz, 85 as score
	union all
	select 'a' name,'英语' clazz, 20 as score
	union all
	select 'b' name,'微积分' clazz, 70 as score
	union all
	select 'b' name,'数学' clazz, 75 as score
	union all
	select 'b' name,'现代' clazz, 71 as score
	union all
	select 'c' name,'物理' clazz, 70 as score
	union all
	select 'c' name,'音乐' clazz, 75 as score
	union all
	select 'c' name,'体育' clazz, 71 as score
)
select *,row_number() over(partition by name order by clazz) rk
from tmp_a;

3. 根据name分组成map结构

注意:这里用到的map_agg是doris里面的,其他数据库不确定有没有。

map_agg(key,value) 这样使用的,这里将序号作为key,后面方便统一取值。

sql 复制代码
with tmp_a as (
	select 'a' name,'语文' clazz, 80 as score
	union all
	select 'a' name,'高数' clazz, 85 as score
	union all
	select 'a' name,'英语' clazz, 20 as score
	union all
	select 'b' name,'微积分' clazz, 70 as score
	union all
	select 'b' name,'数学' clazz, 75 as score
	union all
	select 'b' name,'现代' clazz, 71 as score
	union all
	select 'c' name,'物理' clazz, 70 as score
	union all
	select 'c' name,'音乐' clazz, 75 as score
	union all
	select 'c' name,'体育' clazz, 71 as score
),
tmp_b as (
select *,row_number() over(partition by name order by clazz) rk
from tmp_a
)
select name,
map_agg(rk,clazz) clazz,
map_agg(rk,score) score
from tmp_b group by name;

4. 拆分map

这里必须写死,没其他好方法,而且列是固定写死的。

clazz[1] 这里的1就是上面的放进去的rk的值,由于我们每个人最多只有3门课,

所以可以就取 clazz[1] clazz[2] clazz[3]

sql 复制代码
with tmp_a as (
	select 'a' name,'语文' clazz, 80 as score
	union all
	select 'a' name,'高数' clazz, 85 as score
	union all
	select 'a' name,'英语' clazz, 20 as score
	union all
	select 'b' name,'微积分' clazz, 70 as score
	union all
	select 'b' name,'数学' clazz, 75 as score
	union all
	select 'b' name,'现代' clazz, 71 as score
	union all
	select 'c' name,'物理' clazz, 70 as score
	union all
	select 'c' name,'音乐' clazz, 75 as score
	union all
	select 'c' name,'体育' clazz, 71 as score
),
tmp_b as (
select *,row_number() over(partition by name order by clazz) rk
from tmp_a
), 
tmp_c as (
select name,
map_agg(rk,clazz) clazz,
map_agg(rk,score) score
from tmp_b group by name
)
select name,
clazz[1] clazz_1,score[1] score_1,
clazz[2] clazz_2,score[2] score_2,
clazz[3] clazz_3,score[3] score_3
from tmp_c

最终显示如下,中午没睡觉想了一个中午,脑壳痛,看起来好像也不太复杂,

如果每个人的课程增加时,只需要在最后添加一行即可。

相关推荐
齐 飞33 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
云空34 分钟前
《Python 与 SQLite:强大的数据库组合》
数据库·python·sqlite
暮毅38 分钟前
10.Node.js连接MongoDb
数据库·mongodb·node.js
wowocpp41 分钟前
ubuntu 22.04 server 格式化 磁盘 为 ext4 并 自动挂载 LTS
服务器·数据库·ubuntu
成富1 小时前
文本转SQL(Text-to-SQL),场景介绍与 Spring AI 实现
数据库·人工智能·sql·spring·oracle
songqq271 小时前
SQL题:使用hive查询各类型专利top 10申请人,以及对应的专利申请数
数据库·sql
计算机学长felix1 小时前
基于SpringBoot的“校园交友网站”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·毕业设计·交友
小码的头发丝、2 小时前
Django中ListView 和 DetailView类的区别
数据库·python·django
Karoku0662 小时前
【企业级分布式系统】Zabbix监控系统与部署安装
运维·服务器·数据库·redis·mysql·zabbix
周全全3 小时前
MySQL报错解决:The user specified as a definer (‘root‘@‘%‘) does not exist
android·数据库·mysql