力扣题
1、题目地址
学生地理信息报告
2、模拟表
表:student
| Column Name | Type | 
|---|---|
| name | varchar | 
| continent | varchar | 
- 该表可能包含重复的行。
- 该表的每一行表示学生的名字和他们来自的大陆。
3、要求
一所学校有来自亚洲、欧洲和美洲的学生。
编写解决方案实现对大洲(continent)列的 透视表 操作,使得每个学生按照姓名的字母顺序依次排列在对应的大洲下面。
输出的标题应依次为美洲(America)、亚洲(Asia)和欧洲(Europe)。
测试用例的生成保证来自美国的学生人数不少于亚洲或欧洲的学生人数。
4、示例
输入:
Student 表:
| name | continent | 
|---|---|
| Jane | America | 
| Pascal | Europe | 
| Xi | Asia | 
| Jack | America | 
输出:
| America | Asia | Europe | 
|---|---|---|
| Jack | Xi | Pascal | 
| Jane | null | null | 
5、代码编写
网友代码
SELECT MAX(case when continent = 'America' then name else null end) AS America,MAX(case when continent = 'Asia' then name else null end) AS Asia,MAX(case when continent = 'Europe' then name else null end) AS Europe
FROM (SELECT *, row_number() over(partition by continent order by name) AS cur_rankFROM Student
) AS one
GROUP BY cur_rank
代码分析
首先从子查询里的窗口函数说起,这里作用是将人分到各个大洲,然后根据名字排序得到 cur_rank,即每个人在自己所在州的排名如下
 | America  | Asia | Europe |  | Jack     | Xi   | Pascal |    第一行 cur_rank = 1| Jane     |                    第二行 cur_rank = 2
然后 group by 按照 cur_rank 分组,
 cur_rank = 1 的有 Jack、Xi、Pascal,
 cur_rank = 2 的只有 Jane
然后每个 MAX 会分别遍历这两个组,先遍历 cur_rank = 1 这个组,那么:
- 当第一个 MAX,遇见 Jack 这条记录时,判断 continent 是否等于 America,是,CASE 语句输出 name,即 Jack
- 当第一个 MAX,遇见 Xi 这条记录时,判断 continent 是否等于 America,不是,CASE 语句输出 null
- 当第一个 MAX,遇见 Pascal 这条记录时,判断 continent 是否等于 America,不是,CASE 语句输出 null
至此,第一个MAX里边就是MAX(Jack,null,null),最终输出Jack,因为MAX()或者MIN()计算的时候会忽略null
同理第二个 MAX 则是用于提取出这三个人中,哪些是属于 Asia 的,判断后则有 MAX(null, Xi, null) = Xi
同理第三个 MAX 则是用于提取出这三个人中,哪些是属于 Europe 的,判断后则有 MAX(null, null, Pascal) = Pascal
所以遍历完第一个分组 cur_rank = 1 后,得到的结果就是 [Jane, Xi, Pascal]
| America  | Asia | Europe |
| Jack     | Xi   | Pascal |  
然后再遍历 cur_rank = 2 这个组,这个组里只有的 Jane 这条记录,他属于America
所以三个 MAX 分别是 MAX(Jane)=Jane、MAX(null)=null、MAX(null)=null
所以遍历 cur_rank =2 这个组 得到的结果就是 [Jane, null, null]
| America  | Asia | Europe |
| Jane     | null | null   |