• SQL面试题之按照指定顺序进行多行转一列


    0 需求描述

    user_name course score
    user1 语文 89
    user1 数学 92
    user1 英语 87
    user2 语文 96
    user2 数学 84
    user2 英语 99
    1.将course, score多行转一列
    用户 课程 分数
    user1 语文,数学,英语 89,92,87
    user2 语文,数学,英语 89,92,87

    1 数据准备

    1. create table test01 as
    2. select 'user1' as user_name,'语文' as course,89 as score
    3. union all
    4. select 'user1' as user_name,'数学' as course,92 as score
    5. union all
    6. select 'user1' as user_name,'英语' as course,87 as score
    7. union all
    8. select 'user2' as user_name,'语文' as course,96 as score
    9. union all
    10. select 'user2' as user_name,'数学' as course,84 as score
    11. union all
    12. select 'user2' as user_name,'英语' as course,99 as score

    2 数据分析

    这题初看,很简单,就是简单的多行转一行,用concat_ws(',',collect_list())就能快速解决,但是这样的答案面试官貌似不是很满意,事实上本题是有要求的,需要按照语文、数学、英语这三个顺序进行多行转一列,顺序是固定的。用过collect_list()函数的同学都知道,该函数,一般的结果是顺序不固定的,因此本题的问题点在于如何按照指定顺序进行多行转一行,并且字段对应的值还能对应相一致。

       本题的问题可以得到这样转化,collect_list()函数可以用于窗口函数中,如果我们在做转换的时候指定order by后的顺序,并指定窗口大小为分区全量窗口,那么问题是不是就能得到解决,同样由于语文、数学、英语是字符串,我们直接进行排序得不到想要的答案,所以在进行排序的时候我们可以通过case when进行转换。SQL如下

    1. select user_name
    2. , collect_list(score) over (partition by user_name
    3. order by case
    4. when course = '语文' then 1
    5. when course = '数学' then 2
    6. when course = '英语' then 3 end
    7. rows between unbounded preceding and unbounded following) a
    8. , collect_list(course) over (partition by user_name
    9. order by case
    10. when course = '语文' then 1
    11. when course = '数学' then 2
    12. when course = '英语' then 3 end
    13. rows between unbounded preceding and unbounded following) b
    14. from test01

       

     注意这里的rows between unbounded preceding and unbounded following就表示全量窗口。

    根据上面的结果,我们进行去重就可以得到想要的答案,最终SQL如下:

    1. select user_name
    2. , concat_ws(',', max(b)) as course
    3. , concat_ws(',', max(a)) as score
    4. from (select user_name
    5. , collect_list(score) over (partition by user_name
    6. order by case
    7. when course = '语文' then 1
    8. when course = '数学' then 2
    9. when course = '英语' then 3 end
    10. rows between unbounded preceding and unbounded following) a
    11. , collect_list(course) over (partition by user_name
    12. order by case
    13. when course = '语文' then 1
    14. when course = '数学' then 2
    15. when course = '英语' then 3 end
    16. rows between unbounded preceding and unbounded following) b
    17. from test01
    18. ) t
    19. group by user_name

     2 小结

     本文总结了一种按照指定顺序进行多行转一列的方法,本质上还是对窗口函数的应用。

  • 相关阅读:
    【Linux篇】之samba服务器配置
    openGauss学习笔记-128 openGauss 数据库管理-设置透明数据加密(TDE)
    5 ip的分配
    《Ai企业知识库》-模型实践-rasa开源学习框架-搭建简易机器人-环境准备(针对windows)-02
    ModuleNotFoundError: No module named ‘models‘ 的解决方法
    力扣2596
    TypeScript报错:Object is possibly “null“ 解决方法——断言函数
    面对以太坊合并,投资者有哪些参与策略?
    Qt源码解读(一)Windows消息循环和事件循环机制
    数据结构 | 图
  • 原文地址:https://blog.csdn.net/godlovedaniel/article/details/126661848