50道SQL经典面试题(下)
50道SQL经典面试题(下)
今天继续给小伙伴们补上剩下的25道。
为便于阅读理解,我们还是把表结构和测试数据给大家补上。
一、表结构
1、学生表
Student(Sid,Sname,Sage,Ssex)
学生编号,学生姓名,出生年月,学生性别
2、课程表
Course(Cid,Cname,Tid)
课程编号,课程名称,教师编号
3、教师表
Teacher(Tid,Tname)
教师编号,教师姓名
4、成绩表
SC(Sid,Cid,Score)
学生编号,课程编号,分数
二、表之间的关系
四张表之间的关系如下图:
我们来解读一下上面的关系:
1、课程表Course的课程编号(Cid)作为主键,在成绩表(SC)中可以看到一个或多个学生的课程分数,两表之间是属于1:n的关系。同理学生表(Student)与成绩表(SC)也是1:n的关系
2、教师表Teacher的教师编号(Tid)作为主键,在课程表(Course)中可以带一门或多门课程,两表之间也是属于1:n的关系。
三、测试数据
1、学生表
--建表语句
CREATE TABLE Student (
SID VARCHAR (10),
Sname nvarchar (10),
Sage datetime,
Ssex nvarchar (10)
)
--插入测试数据
INSERT INTO Student VALUES('01' , N'赵雷' , '1990-01-01' , N'男')
INSERT INTO Student VALUES('02' , N'钱电' , '1990-12-21' , N'男')
INSERT INTO Student VALUES('03' , N'孙风' , '1990-05-20' , N'男')
INSERT INTO Student VALUES('04' , N'李云' , '1990-08-06' , N'男')
INSERT INTO Student VALUES('05' , N'周梅' , '1991-12-01' , N'女')
INSERT INTO Student VALUES('06' , N'吴兰' , '1992-03-01' , N'女')
INSERT INTO Student VALUES('07' , N'郑竹' , '1989-07-01' , N'女')
INSERT INTO Student VALUES('08' , N'王菊' , '1990-01-20' , N'女')
结果如下:
2、课程表
--建表语句
CREATE TABLE Course (
CID VARCHAR (10),
Cname nvarchar (10),
TID VARCHAR (10)
)
--插入测试数据
INSERT INTO Course VALUES('01' , N'语文' , '02')
INSERT INTO Course VALUES('02' , N'数学' , '01')
INSERT INTO Course VALUES('03' , N'英语' , '03')
结果如下:
3、教师表
--建表语句
CREATE TABLE Teacher (
TID VARCHAR (10),
Tname nvarchar (10)
)
--插入测试数据
INSERT INTO Teacher VALUES('01' , N'张三')
INSERT INTO Teacher VALUES('02' , N'李四')
INSERT INTO Teacher VALUES('03' , N'王五')
结果如下:
4、成绩表
--建表语句
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)
结果如下:
四、面试题及参考答案
26、查询出只选修两门课程的学生学号和姓名
SELECT SID,Sname
FROM Student
WHERE SID in
(SELECT SID FROM
(SELECT SID,COUNT(CID) 课程数
FROM SC GROUP BY SID
) A
WHERE A.课程数=2
)
27、查询男生、女生人数
SELECT Ssex,COUNT(Ssex) 人数
FROM Student
GROUP BY Ssex
28、查询名字中含有「风」字的学生信息
SELECT * FROM Student
WHERE Sname like '%风%'
29、查询同名同性学生名单,并统计这些人数
SELECT A.*,B.人数
FROM Student A
LEFT JOIN
(SELECT Sname,Ssex,COUNT(*) 人数
FROM Student GROUP BY Sname,Ssex
) B
ON A.Sname=B.Sname and A.Ssex=B.Ssex
WHERE B.人数>1
30、查询 1990 年出生的学生名单
SELECT * FROM Student
WHERE YEAR(Sage)=1990
31、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
SELECT CID,AVG(score) 平均成绩
FROM SC
GROUP BY CID ORDER BY 平均成绩 DESC,CID
32、查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
SELECT A.SID,A.Sname,B.平均成绩
FROM Student A
LEFT JOIN
(SELECT SID,AVG(score) 平均成绩
FROM SC GROUP BY SID
) B on A.SID=B.SID
WHERE B.平均成绩>85
33、查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
SELECT B.Sname,A.score FROM
(SELECT * FROM SC
WHERE score<60
and CID=
(SELECT CID FROM Course
WHERE Cname='数学'
)
) A
LEFT JOIN Student B on A.SID=B.SID
34、查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
SELECT A.SID,B.CID,B.score
FROM Student A
LEFT JOIN SC B on A.SID=B.SID
35、查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
SELECT A.Sname,D.Cname,D.score
FROM
(SELECT B.*,C.Cname
FROM
(SELECT * FROM SC WHERE score>70) B
LEFT JOIN Course C on B.CID=C.CID
) D
LEFT JOIN Student A on D.SID=A.SID
36、查询不及格的课程学生姓名,课程名及分数
SELECT C.Sname,B.Cname,A.score FROM SC A
JOIN Course B ON A.CID=B.CID
JOIN Student C ON A.SID=C.SID
WHERE A.score<60
37、查询课程编号为01且课程成绩在80分以上的学生的学号和姓名
SELECT A.SID,B.Sname
FROM
(SELECT * FROM SC
WHERE score>80 and CID='01'
) A
LEFT JOIN Student B on A.SID=B.SID
38、求每门课程的学生人数(假设每个学生都有参加考试且有成绩)
SELECT CID,COUNT(*) 学生人数
FROM SC
GROUP BY CID
39、成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
SELECT TOP 1 * FROM SC
WHERE CID=
(SELECT CID
FROM Course
WHERE TID=
(SELECT TID FROM Teacher
WHERE Tname='张三'
)
)
ORDER BY score DESC
40、成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
SELECT * FROM
( SELECT *,DENSE_RANK()OVER(ORDER BY score DESC) A
FROM SC
WHERE CID=
(
SELECT CID FROM Course
WHERE TID=
(SELECT TID FROM Teacher
WHERE Tname='张三'
)
)
)B
WHERE B.A=1
41、查询每门功成绩最好的前两名
SELECT * FROM
(SELECT *,ROW_NUMBER()OVER (PARTITION BY CID ORDER BY score DESC)A
FROM SC
)B
WHERE B.A<3
42、统计每门课程的学生选修人数(超过5人的课程才统计),要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
SELECT CID,COUNT(SID) 选修人数
FROM SC
GROUP BY CID
HAVING COUNT(SID)>5
ORDER BY 选修人数 DESC,CID
43、检索至少选修两门课程的学生学号
SELECT SID FROM SC
GROUP BY SID
HAVING COUNT(CID)>=2
44、查询选修了全部课程的学生信息
SELECT SID FROM SC
GROUP BY SID
HAVING COUNT(CID)=
(SELECT DISTINCT COUNT(1) a
FROM Course)
45、查询各学生的年龄,只按年份来算
SELECT SID,DATEDIFF(Year,Sage,GETDATE()) 年龄
FROM Student
46、按照出生日期来算,当前月日小于出生日期的月日则年龄减1岁
SELECT *,
(CASE WHEN
CONVERT(INT,'1'+SUBSTRING(CONVERT(VARCHAR(10),Sage,112),5,8))
< CONVERT(int,'1'+SUBSTRING(CONVERT(VARCHAR(10),GETDATE(),112),5,8))
THEN DATEDIFF(YY,Sage,GETDATE())
ELSE DATEDIFF(YY,Sage,GETDATE())-1
END
)age
FROM Student
47、查询本周过生日的学生
SELECT *,(
CASE WHEN DATENAME(wk,CONVERT
(DATETIME,
(CONVERT(VARCHAR(10),YEAR(GETDATE()))
+SUBSTRING(CONVERT(VARCHAR(10),Sage,112),5,8)
)
)
)=DATENAME(WK,GETDATE())
THEN 1 ELSE 0 END
) 生日提醒
FROM Student
48、查询下周过生日的学生
SELECT *,(
CASE WHEN DATENAME(wk,CONVERT
(DATETIME,
(CONVERT(VARCHAR(10),YEAR(GETDATE()))
+SUBSTRING(CONVERT(VARCHAR(10),Sage,112),5,8)
)
)
)=DATENAME(WK,GETDATE())+1
THEN 1 ELSE 0 END
) 生日提醒
FROM Student
49、查询本月过生日的学生
SELECT *,(
CASE WHEN MONTH(
CONVERT(DATETIME,
(CONVERT(VARCHAR(10),YEAR(GETDATE()))
+SUBSTRING(CONVERT(VARCHAR(10),Sage,112),5,8)
)
)
)=MONTH(GETDATE())
THEN 1 ELSE 0 end) 生日提醒
FROM Student
50、查询下月过生日的学生
SELECT *,(
CASE WHEN MONTH(
CONVERT(DATETIME,
(CONVERT(VARCHAR(10),YEAR(GETDATE()))
+SUBSTRING(CONVERT(VARCHAR(10),Sage,112),5,8)
)
)
)=MONTH(GETDATE())+1
then 1 else 0 end)生日提醒
FROM Student