这是POINT小数点的第 368篇文章点点写在前面:SQL技能是数据分析师面试中必不可少的环节,小数点数据社区也给大家提供了练习SQL题目的地方,以下是pointer Yongfan整理的SQL50题思路与解析之下篇,一定对很多小伙伴非常有帮助。篇幅较长,可以先收藏再学习嗷~

题目快速查找索引


阅读指南

上篇(Pointer干货分享:SQL面试50题思路解答与分类整理(上)聚合函数与表连接)

  • 【第一部分】聚合函数(sum/avg/count/min/max)

  • 【第二部分】表连接(inner join/left join/right join/full join/exclude join)

中篇(Pointer干货分享:SQL面试50题思路解答与分类整理(中)窗口函数与子查询)

  • 【第三部分】窗口函数+Limit+变量(rank/dense rank/row number)

  • 【第四部分】子查询

下篇

  • 【第五部分】CASE

  • 【第六部分】日期函数


【第五部分】CASE

知识要点与易错点总结Case本质上就是IF逻辑判断,可以对多种条件进行控制,有两种写法:第一种简单Case:CASE后面不带表达式。

CASE WHEN 条件1 THEN 结果1WHEN 条件2 THEN 结果2     .......ELSE 结果nEND

第二种Case搜索函数:CASE 后面带表达式,此时WHEN 后面的则是该表达式可能的值。

CASE 表达式WHEN 条件的值1 THEN 结果1WHEN 条件的值2 THEN 结果2     .......ELSE 结果nEND

注意:case函数只返回第一个符合条件的值,剩下的case部分将会被自动忽略。CASE题目整理(完整题目列表见文章最后)【17. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比】***第17题和第14题都需要计算百分比,这里主要解释统计各分数段的逻辑,计算百分比的内容请参见第14题

select a.cid, b.cname,sum(case when a.cscore>=85 then 1 else 0 end) as '[100-85]',sum(case when a.cscore>=70 and a.cscore<85 then 1 else 0 end) as '[85-70]',sum(case when a.cscore>=60 and a.cscore<70 then 1 else 0 end) as '[70-60]',sum(case when a.cscore<60 then 1 else 0 end) as'[60-0]'from score as a join course as bon a.cid = b.cidgroup by a.cid;
  • 要统计各分数段人数,产生多个分数段新列,要用case+sum来完成

  • 首先用case语句来创建分数段。例如第一个case语句,代表逐行扫描score表每一行数据,找到cscore>=85就加1,最后用sum函数统计这个分数段有多少个人。以此类推

  • 为了显示课程名称,还要join成绩表和课程表

  • 最后用cid分组,返回三行结果,显示三门课程的各分数段人数

【14. 查询各科成绩最高分、最低分和平均分,以如下形式显示(题目略作修改):

  • 课程 ID,课程 name,最高分,最低分,平均分

  • 成绩分段如下:A为优秀>=90,B为良好80-90,C为中等70-80,D为及格>=60,Fail为不及格<60

  • 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列】

解法1:CASE

select a.cid, b.cname, count(a.sid) as 选修人数, max(a.cscore) as 最高分, min(a.cscore) as 最低分, avg(a.cscore) as 平均分,sum(case when a.cscore>=90 then 1 else 0 end) / count(a.sid) as 'A',sum(case when a.cscore>=80 and a.cscore<90 then 1 else 0 end) / count(a.sid) as 'B',sum(case when a.cscore>=70 and a.cscore<80 then 1 else 0 end) / count(a.sid) as 'C',sum(case when a.cscore>=60 and a.cscore<70 then 1 else 0 end) / count(a.sid) as 'D',sum(case when a.cscore<60 then 1 else 0 end) / count(a.sid) as 'Fail'from score as ajoin course as bon a.cid = b.cidgroup by a.cidorder by 选修人数 desc, cid asc;
  • 要统计各分数段人数,产生多个分数段新列,要用case来完成,原理与上一题一致

  • 计算百分比,例如及格率,就是用case的结果/成绩表学生总人数

  • 最后进行排序,先用选修人数降序排列,然后用课程编号cid升序排列

解法2:IF

select score.cid, cname,count(sid) as 选修人数, max(cscore) as 最高分,min(cscore) as 最低分, avg(cscore) as 平均分,count(if(cscore between 90 and 100, sid, null)) / count(sid) as A,count(if(cscore between 80 and 89, sid, null)) / count(sid) as B,count(if(cscore between 70 and 79, sid, null)) / count(sid) as C,count(if(cscore between 60 and 69, sid, null)) / count(sid) as D,count(if(cscore between 0 and 59, sid, null)) / count(sid) as Failfrom scoreleft join courseon score.cid=course.cidgroup by score.cid;
  • IF的语法规则是:IF(A,B,C),如果A条件为True,那么执行B,否则执行C

  • MySQL中,使用between运算符会选取包含头尾两个数值的范围,例如between 90 and 100,就是选取90分到100分的数据

  • 例如第一个IF语句,当分数cscore在90-100分(包含头尾)时,返回值为学生编号sid,否则返回null,所以使用count就可以得到总共有多少个符合条件的sid

补充内容:在查询结果中返回百分比并保留小数点后两位这部分算是自己加的内容吧,主要觉得上面查询出来的百分比返回的0.3333之类的数值可读性不好,所以想要转换成33.33%这样的形式,具体方法就是先用cast函数取小数点后两位,然后用concat函数拼接数值和百分号,代码修改如下,供参考:

#修改第14题解法1的代码:select a.cid, b.cname, concat(cast(100*sum(case when a.cscore>=90 then 1 else 0 end) / count(*) as decimal(18,2)), '%') as 'A',concat(cast(100*sum(case when a.cscore>=80 and a.cscore<90 then 1 else 0 end) / count(*) as decimal(18,2)), '%') as 'B',concat(cast(100*sum(case when a.cscore>=70 and a.cscore<80 then 1 else 0 end) / count(*) as decimal(18,2)), '%') as 'C',concat(cast(100*sum(case when a.cscore>=60 and a.cscore<70 then 1 else 0 end) / count(*) as decimal(18,2)), '%') as 'D',concat(cast(100*sum(case when a.cscore<60 then 1 else 0 end) / count(*) as decimal(18,2)), '%') as 'Fail'from score as ajoin course as bon a.cid = b.cidgroup by a.cid;
  • cast函数的语法为:cast(expr AS data_type),上述代码第二行的expr就是100*sum(case when a.cscore>=90 then 1 else 0 end) / count(*),先计算出百分比的数值。data_type就是decimal(18,2),两个参数代表最大18位数,小数点后保留2位

  • 然后用concat函数拼接cast函数转换出来的数字与百分号%


【第六部分】日期函数

知识要点与易错点总结MySQL数据库的日期函数有很多,参见:w3cschool.cn/sql/82rg1o这里讲一些经常用到的日期函数:

  • CURDATE() = CURRENT_DATE():返回当前日期年月日,例如2020-04-28

  • CURTIME() = CURRENT_TIME():返回当前时间时分秒,例如22:10:51

  • DATEDIFF():计算两个日期相差多少天,有两个参数:

    • 第一参数begin date

    • 第二参数end date

  • TIMESTAMPDIFF():在 datetime 表达式上减去一段时间,允许其参数具有混合类型(date或者datetime都可以),有三个参数:

    • 第一参数unit,是确定end-begin结果的单位,可以是year,month,week,day等

    • 第二参数begin date

    • 第三参数end date

  • DATE():从 date 或者 datetime 表达式中提取出日期部分

  • WEEK():返回日期参数是一年中的第几周,有两个参数:

    • 第一参数date,即需要查询星期数的日期

    • 第二参数mode是可选参数,用于指定一周起始于周日还是周一,以及返回值的范围应该是 0 到 53,还是 1 到 53

  • MONTH():返回日期参数的月份

  • YEAR():返回日期参数中的年份

  • STR_TO_DATE():将字符串转换为日期数据

日期函数题目整理(完整题目列表见文章最后)【40. 查询各学生的年龄,只按年份来算】

select sid, sname, (year(curdate()) - year(sage)) as 年龄from student;
  • year() 函数返回年份,curdate() 函数返回当前日期

  • (year(curdate()) - year(sage)) 这个表达式最外面的括号可以不写

【41. 按照出生日期来算,如果当前月日 < 出生日期的月日,年龄减一】

select sid, sname,timestampdiff(year, sage, curdate()) as 年龄from student;
  • 按出生日期来算,可以用更精确的timestampdiff函数求时间差,第一参数设定为year

【42. 查询本周过生日的学生】***经朋友提醒,发现本题网上一些答案的写法是使用weekofyear()函数来解,给出一个日期参数,返回结果为该日期是那一年的第几周。但在这里其实不能用,例如sid=03号同学,生日是1990-05-20,使用weekofyear得出1990年的5月20号是当年的第20周。但是weekofyear计算出2020年5月20日是今年的第21周,并没有完成题目要求。***注意:本来应该写now() 或curdate() 函数返回当前时间,但为了验证题目,下面的解法都用字符串日期'2020-05-20'代替

#weekofyear函数查找03号学生的生日所在周select weekofyear(student.sage) from student where sid=03;

#weekofyear函数查找2020年5月20日所在周select weekofyear('2020-05-20');

#错误解法示例:select * from student where weekofyear(student.sage) = weekofyear('2020-05-20');
  • 可以看到,如果用weekofyear(student.sage) = weekofyear('2020-05-20') 的写法,并没有返回03号同学的数据

正确的方法是,提取学生表中sage的出生日期数据的“月”和“日”,删掉“年”,而是把当前年份的“年”与sage的“月”和“日”拼接,然后再用week() 函数确定该日期是一年中的第几周。week() 函数有一个可选参数mode,用来确定计算周数的逻辑,如果不写则默认值为0,代表“一周的第一天是星期日,且周数范围为0-53”。mode参数可以根据实际需要进行调整,这里就使用默认值。

#最终代码select *, MONTH(Sage) as 月, DAY(Sage) as 日,CONCAT_WS('-',Year(now()),MONTH(Sage),DAY(Sage)) as 拼接日期 from student having WEEK('2020-05-20') = WEEK(拼接日期);
  • 这段代码的重点在于拼接日期,使用第四部分【子查询】里提到过的知识点CONCAT_WS函数将当前日期的年份Year(now()),sage的月,sage的日,拼接成一个YYYY-MM-DD的字符串,命名为新字段“拼接日期”

【43. 查询下周过生日的学生】

select *, MONTH(Sage) as 月, DAY(Sage) as 日,CONCAT_WS('-',Year(now()),MONTH(Sage),DAY(Sage)) as 拼接日期 from student having WEEK(now()) + 1 = WEEK(拼接日期);
  • 基于上一题,下周过生日就是当前日期的周数+1

【44. 查询本月过生日的学生】

select * from student where month(student.sage) = month(curdate());
  • month() 函数返回日期参数的月份

【45. 查询下月过生日的学生】

select * from student where month(student.sage) = month(curdate()) + 1;
  • 基于上一题,下月过生日就是当前日期的月份+1

【24. 查询 1990 年年出生的学生名单】

select * from studentwhere YEAR(sage) = 1990;
  • 用year() 函数确定日期参数的年份


其他

剩下几道题的知识点比较散,放在一起说:LIKE 运算符

  • 常与通配符 % 和 _ 配合使用

  • % 代表任意个字符,可以是0个,1个,或多个

  • _ 代表1个字符,可以把 _ 当成占位符

  • 注意:Access使用 ? 而不是 _

【5. 查询「李」姓老师的数量】

select * from teacherwhere teacher.tname like '李%';

【22. 查询名字中含有「风」字的学生信息】

select * from student where sname like '%风%';

附录

题目列表:1.1 查询"01"课程比"02"课程成绩高的学生的信息及课程分数1.2 查询同时上过"01"课程和"02"课程的学生1.3 查询上过"01"课程但可能没上过"02"课程的学生 (这种情况显示为 null)1.4 查询没上过"01"课程,只上过"02"课程的学生2. 查询平均成绩大于等于 60 分的同学的学生编号、学生姓名和平均成绩3. 查询在 SC 表存在成绩的学生信息4. 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null)5. 查询「李」姓老师的数量6. 查询学过张三老师授课的同学的信息7. 查询没有学全所有课程的同学的信息8. 查询至少有一门课与学号为"01"的同学所学相同的同学的信息9. 查询和"01"号的同学学习的课程完全相同的其他同学的信息10. 查询没学过"张三"老师讲授的任一门课程的学生姓名11. 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩12. 检索" 01 "课程分数小于 60,按分数降序排列的学生信息13. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩14. 查询各科成绩最高分、最低分和平均分,以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率(及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90)要求输出课程号和选修人数,查询结果按人数降序排列列,若人数相同,按课程号升序排列15.1 按各科成绩进行排序,并显示排名, 成绩重复时保留名次空缺15.2 按各科成绩进行排序,并显示排名, 成绩重复时合并名次16. 查询学生的总成绩,并进行排名,总分重复时保留名次空缺17. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比18. 查询各科成绩前三名的记录19. 查询每门课程被选修的学生数20. 查询出只选修两门课程的学生学号和姓名21. 查询男生、女生人数22. 查询名字中含有「风」字的学生信息23. 查询同名同性学生名单,并统计同名人数24. 查询 1990 年年出生的学生名单25. 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列26. 查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩27. 查询课程名称为「数学」,且分数低于 60 的学生姓名和分数28. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)29. 查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数30. 查询不及格的课程31. 查询课程编号为 01 且课程成绩在 80 分及以上的学生的学号和姓名32. 求每门课程的学生人数33. 成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩34. 成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩35. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩36. 查询所有课程成绩第二名到第三名的学生信息及课程成绩37. 统计每门课程的学生选修人数(超过 5 人的课程才统计)38. 检索至少选修两门课程的学生学号39. 查询选修了全部课程的学生信息40. 查询各学生的年龄,只按年份来算41. 按照出生日期来算,如果当前月日 < 出生年月的月日,年龄减一42. 查询本周过生日的学生43. 查询下周过生日的学生44. 查询本月过生日的学生45. 查询下月过生日的学生小数点数据社区就可以练习SQL50题和各类小挑战,申请社区内测可以添加数苗(备注 内测):point_shumiao

END

加入POINT.

长按扫码添加小夏微信

数据 | 社区 | 职场 | 比赛

POINT.小数点Excel-VBA课程(第十三期)正式预售点击图片加入POINT.小数点Python编程课程(第十三期)正式预售点击图片加入Pointer超棒,在看支持!

abap 取日期最大_Pointer干货分享:SQL面试50题思路解答与分类整理(下)CASE与日期函数...相关推荐

  1. max日期最大值为0_【SQL】SQL面试50题思路解答与分类整理(下)CASE与日期函数...

    题目快速查找索引 阅读指南 上篇 [第一部分]聚合函数(sum/avg/count/min/max) [第二部分]表连接(inner join/left join/right join/full jo ...

  2. sql查询三级菜单分类_SQL面试50题——思路解答与分类整理(中)窗口函数与子查询...

    让我们每天都进步一点点 题目快速查找索引 阅读指南 上篇:SQL面试50题--思路解答与分类整理(上)聚合函数与表连接 [第一部分]聚合函数(sum/avg/count/min/max) [第二部分] ...

  3. 练习总结sql面试50题(2021-12-27完结)

    参考 [数据分析]- SQL面试50题 - 跟我一起打怪升级 一起成为数据科学家_哔哩哔哩_bilibili 图解SQL面试题:经典50题 - 知乎 sql面试题:topN问题 sql 分组查询 分组 ...

  4. SQL 面试用题(重点)

    SQL 面试用题 employees 表: EMPLOYEE_ID NUMBER(6) FIRST_NAME VARCHAR2(20) LAST_NAME VARCHAR2(25) EMAIL VAR ...

  5. 【SQL经典50题】9.查询和“ 01 “号的同学学习的课程完全相同的其他同学的信息【正解】

    查询所用的表结构见https://blog.csdn.net/zjhbeautiful/article/details/108065336 SQL经典50题第9题正解 题目:查询和" 01 ...

  6. c语言解析sql语句_sql语句面试50题(Mysql版附解析)

    本人最近在自学sql,从开始学到自己写完本练习50题大概花了12天的时间. 学习路径:<sql基础教程>第1遍(3天)→知乎中的sql网课+leetcode刷题(4天)→牛客网刷题(2天) ...

  7. 经典sql语句50题_SQL面试经典50题:带你从建表开始

    大家好,相信很多学习数据分析的小伙伴在面试前都经历过刷题,本系列小编将带大家一起来刷一刷SQL面试必会的经典50题. 当然本系列文章不单单是刷题,小编会带着大家梳理一下解题时用到的知识点,所以基础比较 ...

  8. 100天SQL面试刷题 Day004

    先看题目自己试着解一下,有困难的同学可以先看考点解析试下, 最后再看SQL解答,有不同意见和解法的欢迎评论区留言交流 快速定位 题目: 结果输出 考点解析 SQL代码 来源:大厂面试真题 题目: 表s ...

  9. 如何以正确地姿势AK SQL查询50题(精华篇)

    前言------ AK: ALL Killed 这学期学数据库系统概论,作为一个初学者,必须先熟练掌握SQL的基本查询语句,在完成了老师的SQL50题之后,我把我自己地AK姿势记录下来, 便于回忆之余 ...

最新文章

  1. 数据中心是虚拟现实的基石
  2. android gradle.properties
  3. vuex-along解决vuex中存储的数据在页面刷新之后失去的问题
  4. python3.4安装suds
  5. Matplotlib-scatter-绘制散点图
  6. android 蒙层广告1,subnvue安卓机打开只显示蒙层,没有任何内容【报Bug】
  7. 缓冲文件系统和非缓冲文件系统
  8. EasyRecovery15永久免费数据恢复软件
  9. onenote使用python开发_我应该用onenote还是印象笔记?
  10. linux中,ls -l命令显示的total的含义。
  11. 电商设计的文字的选择与排版
  12. Leetcode刷题笔记——剑指offer II (六)【图】
  13. API大全 汇总(转载)
  14. 高端数据中心交换机散热系统大比拼
  15. Strings, bytes, runes and characters in Go
  16. 算法 - 鸡尾酒排序(CocktailShaker_sort)
  17. linux中shell的循环
  18. 【Codecs系列】HEVC-SCC编码技术汇总
  19. 徐无忌MySQL笔记:索引的使用规则
  20. The Data Science of Gaming and Fantasy Sports 游戏与幻想体育的数据科学 Lynda课程中文字幕

热门文章

  1. jsp 定义java类_在JSP中定义一个类
  2. 如何设置工作流到了某一节点自动执行java方法_2019年JAVA最常见面试题汇总(收藏)...
  3. airpassengers数据集_12个Pandas amp;amp; Numpy函数:数据分析提速50%不是问题!
  4. deny后加to do还是doing_become to do还是doing
  5. python实现单链表快速排序升序linkedqueue_LeetCode 总结 - 搞定 Linked List 面试题
  6. android studio光标变成黑块,解决Android Studio 代码无提示无颜色区分问题
  7. mysql qps 索引查询_【MySQL】MySQL配置调优之 QPS/TPS/索引缓存命中率、innoDB索引缓存命中率、查询缓存命中率查看...
  8. #pragma pack(push,1)与#pragma pack(1)的区别(转)
  9. vscode+TCC快捷编译c语言
  10. vue keepalive 动态设置缓存