T618:sql行转列求学生地理报告

题目:
618. 学生地理信息报告

表: student

±------------±--------+
| Column Name | Type |
±------------±--------+
| name | varchar |
| continent | varchar |
±------------±--------+
该表可能包含重复的行。
该表的每一行表示学生的名字和他们来自的大陆。

一所学校有来自亚洲、欧洲和美洲的学生。

编写解决方案实现对大洲(continent)列的 透视表 操作,使得每个学生按照姓名的字母顺序依次排列在对应的大洲下面。输出的标题应依次为美洲(America)、亚洲(Asia)和欧洲(Europe)。

测试用例的生成保证来自美国的学生人数不少于亚洲或欧洲的学生人数。

返回结果格式如下所示。

T618:sql行转列求学生地理报告_第1张图片
分析:
先来看看直观的想法,利用case when来进行分列操作,直接用以下代码:

select
case when continent = 'America' then name end as America,
case when continent = 'Asia' then name end as Asia,
case when continent = 'Europe' then name end as Europe
from student

将得到以下结果:
T618:sql行转列求学生地理报告_第2张图片

可以看到有很多的null,为了去掉这些null,我们进行以下操作:

  1. 先用row_number() over()根据国家进行分组排序:
select
*,
row_number() over(partition by continent order by name) rn
from
student

得到如下结果:
T618:sql行转列求学生地理报告_第3张图片
2. 利用case when进行行转列

select
case when continent = 'America' then name end as America,
case when continent = 'Asia' then name end as Asia,
case when continent = 'Europe' then name end as Europe
from
(
select
*,
row_number() over(partition by continent order by name) rn
from
student
)a

进行以上代码操作,会产生4行数据,如下:
T618:sql行转列求学生地理报告_第4张图片

可以看到有很多null,为了去掉过多的null,需进行第三步操作。
3. 按照rn进行分组,并对每组数据取max或者min
这样做可以去掉多余的null,使得每一列下如果name非空就只保留name。
(补充:max和min在计算中时忽略null的,这里用max或者min是因为计算的是字符串类型,如果是数值型可以用sum)
因此,最终题解为:

-- 行转列
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) rn 
    from 
Student
) a 
group by rn

ref:力扣
作者:Eloquent CartwrightAq0
链接:https://leetcode.cn/problems/students-report-by-geography/solutions/1758057/c-by-eloquent-cartwrightaq0-2grl/

你可能感兴趣的:(sql语言,sql,数据库)