SQL笔试经典50题及答案解析(题目41-50)

前言
最近博主在准备数据分析岗位的笔试和面试,其中的考察重点就是SQL。听说练了这50道题目(题目和数据来源参考:互联网校招SQL笔试经典50题及答案解析),什么现场手撕SQL统统都不怕,我就赶紧来练习了!壮士们,练完以后就什么都不怕啦~

我看了原博主的查询语句,有些不够简洁,有些或许存在问题。下面都是我自己写的查询语句,保证在Navicat上跑得通,但是不排除存在写的不对不好的地方,欢迎大家提出来,一起学习,共同进步。

环境:
Navicat Premium 12

说明:
本篇练习的是题目41-50,哪怕不简单,大家也不用害怕,take it easy~

其余题目请参考链接:
SQL笔试经典50题及答案解析(题目1-10)
SQL笔试经典50题及答案解析(题目11-20)
SQL笔试经典50题及答案解析(题目21-30)
SQL笔试经典50题及答案解析(题目31-40)

创建表

表说明

本次创建的表有四张:

  • 学生表(student): 包含 学生号,学生姓名,出生年月,性别 四个字段
  • 教师表(teacher): 包含教师号,教师姓名 两个字段
  • 成绩表(sc): 包含学生号,课程号,成绩 三个字段
  • 课程表(course): 包含课程号,课程名,教师号 三个字段

表创建

# 创建学生表
create table Student(sid varchar(10),sname varchar(10),sage datetime,ssex nvarchar(10));
insert into Student values('01' , '赵雷' , '1990-01-01' , '男');
insert into Student values('02' , '钱电' , '1990-12-21' , '男');
insert into Student values('03' , '孙风' , '1990-05-20' , '男');
insert into Student values('04' , '李云' , '1990-08-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吴兰' , '1992-03-01' , '女');
insert into Student values('07' , '郑竹' , '1989-07-01' , '女');
insert into Student values('08' , '王菊' , '1990-01-20' , '女');

# 创建课程表
create table Course(cid varchar(10),cname varchar(10),tid varchar(10));
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');


# 创建教师表
create table Teacher(tid varchar(10),tname varchar(10));
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');


# 创建成绩表
create table SC(sid varchar(10),cid varchar(10),score decimal(18,1));
insert into SC values('01' , '01' , 80);
insert into SC values('01' , '02' , 90);
insert into SC values('01' , '03' , 99);
insert into SC values('02' , '01' , 70);
insert into SC values('02' , '02' , 60);
insert into SC values('02' , '03' , 80);
insert into SC values('03' , '01' , 80);
insert into SC values('03' , '02' , 80);
insert into SC values('03' , '03' , 80);
insert into SC values('04' , '01' , 50);
insert into SC values('04' , '02' , 30);
insert into SC values('04' , '03' , 20);
insert into SC values('05' , '01' , 76);
insert into SC values('05' , '02' , 87);
insert into SC values('06' , '01' , 31);
insert into SC values('06' , '03' , 34);
insert into SC values('07' , '02' , 89);
insert into SC values('07' , '03' , 98);

表显示

学生表如下:
在这里插入图片描述
教师表如下:
在这里插入图片描述
成绩表如下:
在这里插入图片描述
课程表如下:
在这里插入图片描述

题目

题目42(重要)

查询每门功课成绩最好的前两名
情况1: 考虑并列的排名,如果第一名或者第二名有并列,全部找出来

#考虑并列的排名,如果第一名或者第二名有并列,全部找出来
SELECT *
FROM
(
	SELECT *,dense_rank() over (PARTITION BY cid ORDER BY score DESC) AS srank 
	FROM sc
) AS tmp
WHERE tmp.srank<=2

运行结果
在这里插入图片描述
从上述结果看出,这种情况考虑并列结果,80分排名是第一,因此,所有排名第一的同学都被取了出来;接下来是76分排名第二,所以所有76分的同学都被取了出来。

情况2: 不考虑并列的排名,就取2人

#不考虑并列的排名,就取2人
SELECT *
FROM
(
	SELECT *,ROW_NUMBER() over (PARTITION BY cid ORDER BY score DESC) AS srank
	FROM sc
) AS tmp
WHERE tmp.srank<=2

运行结果
在这里插入图片描述
从上述结果可以看出,这种做法不考虑并列,仅仅是取出2名同学的信息。

题目43

统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

SELECT cid,COUNT(DISTINCT sid) AS cnt
FROM sc
GROUP BY cid
HAVING cnt>5   -- 知识点:having里面可以使用select里面定义的别名,但是where不行
ORDER BY cnt DESC,cid ASC

注意事项

  • having子句里面可以使用select里面定义的别名,但是where子句就不行,因为执行顺序where靠前,select靠后。

运行结果
在这里插入图片描述

题目44

检索至少选修两门课程的学生学号

SELECT sid,COUNT(DISTINCT cid) AS cnt
FROM sc
GROUP BY sid
HAVING COUNT(DISTINCT cid)>=2

运行结果
在这里插入图片描述

题目45

查询选修了全部课程的学生信息

SELECT sid
FROM sc
GROUP BY sid
HAVING COUNT(DISTINCT cid)  
= (SELECT COUNT(DISTINCT cid) FROM sc)

运行结果
在这里插入图片描述

题目46

查询各学生的年龄
方法1: TIMESTAMPDIFF函数规定返回值类型是YEAR,返回值为后者-前者

# 方法1:TIMESTAMPDIFF函数规定返回值类型是YEAR,返回值为后者-前者
SELECT *,TIMESTAMPDIFF(YEAR,sage,CURRENT_TIMESTAMP()) AS age 
FROM student

方法2: 使用year提取年份

# 方法2:# 使用year提取年份
SELECT *,YEAR(CURRENT_DATE())-YEAR(sage) AS age 
FROM student

注意事项

  • TIMESTAMPDIFF函数使用方法为:
    • TIMESTAMPDIFF(unit,date1,date2)
    • 规定返回值类型是unit
    • 返回值为后者-前者
  • 考察时间函数的使用,常见的提取时间的函数
    • YEAR(DATE) 提取年份
    • MONTH(DATE) 提取月
    • DAY(DATE) 提取日

运行结果
在这里插入图片描述

题目47(重要)

查询本周过生日的学生

# 同一天,在不同的年份,可能不是同一周,例子很多
SELECT WEEKOFYEAR('2020-03-17') AS week1,WEEKOFYEAR('2018-03-17') AS week2
# 运行结果:week1是12,week2是11

# 解决办法:放在同一年进行比较
SELECT * 
FROM student
WHERE WEEKOFYEAR(CONCAT('2020-',SUBSTR(sage, 6,5))) = WEEKOFYEAR(CURDATE())

注意事项

  • 同一天,在不同的年份,可能不是同一周,例子很多
  • 解决办法:使用substr函数把原来的月份和日提取出来,然后使用concat函数和今年的年份连接起来,这样就做到了在同一年比较,然后再比较结果,这种做法合理一点。

题目48

查询下周过生日的学生

SELECT * 
FROM student
WHERE WEEKOFYEAR(CONCAT('2020-',SUBSTR(sage, 6,5))) = WEEKOFYEAR(DATE_ADD(CURDATE())+1

注意事项

题目49

查询本月过生日的学生

# 使用month提取月份
SELECT * 
FROM student
WHERE MONTH(sage) = MONTH(CURRENT_DATE())

注意事项

  • 和下一道题对比学习

题目50(重要)

查询下月过生日的学生

SELECT	sid,sname,sage
FROM student
WHERE MONTH(sage) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH))

注意事项

  • 一般大家都会想到给当前月份+1,就是下个月。但是碰到12月也加一就有问题了,毕竟没有13月呀!
  • 解决办法:使用DATE_ADD/ DATE_SUB函数,就能给当前日期加上或者减去固定的时间,比如求12月后面的1个月,可以得到结果是一月。
  • 知识点:MySQL DATE_SUB() 函数
# 求12月后面的1个月,结果是'2020-01-01'
SELECT DATE_ADD('2019-12-1',INTERVAL 1 MONTH)
发布了8 篇原创文章 · 获赞 2 · 访问量 537

猜你喜欢

转载自blog.csdn.net/weixin_43890183/article/details/104924751
今日推荐