• 1412. 查找成绩处于中游的学生


    SQL架构

    表: Student

    +---------------------+---------+
    | Column Name         | Type    |
    +---------------------+---------+
    | student_id          | int     |
    | student_name        | varchar |
    +---------------------+---------+
    student_id 是该表主键.
    student_name 学生名字.

    表: Exam

    +---------------+---------+
    | Column Name   | Type    |
    +---------------+---------+
    | exam_id       | int     |
    | student_id    | int     |
    | score         | int     |
    +---------------+---------+
    (exam_id, student_id) 是该表主键.
    学生 student_id 在测验 exam_id 中得分为 score.
    

    成绩处于中游的学生是指至少参加了一次测验, 且得分既不是最高分也不是最低分的学生。

    写一个 SQL 语句,找出在 所有 测验中都处于中游的学生 (student_id, student_name)

    不要返回从来没有参加过测验的学生。返回结果表按照 student_id 排序。

    查询结果格式如下。

    Student 表:
    +-------------+---------------+
    | student_id  | student_name  |
    +-------------+---------------+
    | 1           | Daniel        |
    | 2           | Jade          |
    | 3           | Stella        |
    | 4           | Jonathan      |
    | 5           | Will          |
    +-------------+---------------+
    
    Exam 表:
    +------------+--------------+-----------+
    | exam_id    | student_id   | score     |
    +------------+--------------+-----------+
    | 10         |     1        |    70     |
    | 10         |     2        |    80     |
    | 10         |     3        |    90     |
    | 20         |     1        |    80     |
    | 30         |     1        |    70     |
    | 30         |     3        |    80     |
    | 30         |     4        |    90     |
    | 40         |     1        |    60     |
    | 40         |     2        |    70     |
    | 40         |     4        |    80     |
    +------------+--------------+-----------+
    
    Result 表:
    +-------------+---------------+
    | student_id  | student_name  |
    +-------------+---------------+
    | 2           | Jade          |
    +-------------+---------------+
    
    对于测验 1: 学生 1 和 3 分别获得了最低分和最高分。
    对于测验 2: 学生 1 既获得了最高分, 也获得了最低分。
    对于测验 3 和 4: 学生 1 和 4 分别获得了最低分和最高分。
    学生 2 和 5 没有在任一场测验中获得了最高分或者最低分。
    因为学生 5 从来没有参加过任何测验, 所以他被排除于结果表。
    由此, 我们仅仅返回学生 2 的信息。

    用union:

    1. select
    2. s.student_id,s.student_name
    3. from
    4. (
    5. select
    6. distinct student_id
    7. from
    8. Exam
    9. where
    10. student_id not in
    11. (
    12. select
    13. s1.student_id
    14. from
    15. (select
    16. student_id, max(score) over(partition by exam_id) ms,score s
    17. from
    18. Exam
    19. ) s1
    20. where s1.ms = s1.s
    21. union all
    22. select
    23. s1.student_id
    24. from
    25. (select
    26. student_id, min(score) over(partition by exam_id) ms,score s
    27. from
    28. Exam
    29. ) s1
    30. where s1.ms = s1.s
    31. ) ) ss1 left join Student s on ss1.student_id = s.student_id
    32. order by student_id
    1. select
    2. s.student_id,s.student_name
    3. from
    4. (
    5. select
    6. distinct student_id
    7. from
    8. Exam
    9. where
    10. student_id not in #在考试里 不在 下面 表里的 学生id 就是 题中 需要的
    11. (
    12. select
    13. s1.student_id
    14. from
    15. (select
    16. student_id, max(score) over(partition by exam_id) ms,score s # 选出考试成绩 最大的 学生id
    17. from
    18. Exam
    19. ) s1
    20. where s1.ms = s1.s
    21. union all # 上下两表 拼接
    22. select
    23. s1.student_id
    24. from
    25. (select
    26. student_id, min(score) over(partition by exam_id) ms,score s # 选出 考试成绩 最小的 学生id
    27. from
    28. Exam
    29. ) s1
    30. where s1.ms = s1.s
    31. ) ) ss1 left join Student s on ss1.student_id = s.student_id
    32. order by student_id

    开两个窗:

    1. select
    2. student_id,student_name
    3. from
    4. Student
    5. where student_id in
    6. (
    7. select
    8. s1.student_id
    9. from
    10. (
    11. select
    12. student_id,if(dense_rank() over(partition by exam_id order by score)=1,1,0) dr1,if(dense_rank() over(partition by exam_id order by score desc)=1,1,0) dr2
    13. from
    14. Exam
    15. ) s1
    16. group by
    17. s1.student_id
    18. having sum(s1.dr1) = 0 and sum(s1.dr2) = 0
    19. )
    1. select
    2. student_id,student_name
    3. from
    4. Student
    5. where student_id in
    6. (
    7. select
    8. s1.student_id #题中 需要的 学生id
    9. from
    10. (
    11. select
    12. student_id,if(dense_rank() over(partition by exam_id order by score)=1,1,0) dr1,if(dense_rank() over(partition by exam_id order by score desc)=1,1,0) dr2 # 按score 降序 和升序 标号 标号为1的置为1 标号 为2的 置为0 (便于后期用sum为零选出想要的值)
    13. from
    14. Exam
    15. ) s1
    16. group by
    17. s1.student_id
    18. having sum(s1.dr1) = 0 and sum(s1.dr2) = 0
    19. )

    笔记:

    1窗口函数只能出现在select 和order by 字句中
    2如果查询的其他部分( where,GROUP BY, having)需要窗口函数,请使用子查询,在子查询使用窗口函数
    3 如果查询使用聚合或者group by 请记住窗口函数只能处理分组后的结果,而不是原始的表数据.

  • 相关阅读:
    gitlab查看、修改用户和邮箱,gitlab生成密钥
    iOS自动化测试框架Kiwi快速上手
    3.3日学习打卡----初学Redis(一)
    在Linux中搭建Mosquitto MQTT协议消息服务端并结合内网穿透工具实现公网访问
    Jmeter —— jmeter参数化实现
    Leetcode 2290. 到达角落需要移除障碍物的最小数目
    vulnhub靶机DC9
    大数据_HDFS原理
    SpringBoot中个常见的几个问题
    解决因为修改SELINUX配置文件出错导致Faild to load SELinux poilcy无法进入CentOS7系统的问题
  • 原文地址:https://blog.csdn.net/m0_69157845/article/details/125478273