SQL50题解题思路 Q1-5




SQL50题解题思路 Q1-5

SQL50题解题思路 Q1-5

Q6-12

Q13-16

Q17-23

注意事项

建表语句及题目参考于超经典SQL练习题,做完这些你的SQL就过关了 - flycat296的博客 - CSDN博客,不同来源的题目和建表语句会有细微差别。

本解题思路仅代表个人思路,并非一定正确,仅供参考。建议观看答案前自己建表做一遍。

1. 查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数

思路

题目要求可以分成两部分,查询的信息为学生的信息及课程分数,条件是" 01 "课程比" 02 "课程成绩高。

学生信息和课程分数在两个不同的表,所以需要用join把两个表连接起来。但是直接连接的话每个学生会有多条记录对应不同的课程,课程成绩互相比较会比较麻烦,而观察数据库可知课程一共只有三门。所以可以考虑把每一门课程的成绩分别连接到学生信息表上。用

select S#,score score1 from SC where C# = '01'

选择某一门课程的成绩并给成绩整一个别名,然后分别连接到Student表上。考虑到有些学生没有选修某些课程所以用left join确保数据完整。连接之后再比较" 01 "课程和" 02 "课程成绩就比较简单了,直接一句where搞定。

代码

SELECT s.*, c1.score1, c2.score2, c3.score3
    FROM Student s
    LEFT JOIN(SELECT S#, score score1 FROM SC WHERE C# = '01')c1 ON s.S#=c1.S#
    LEFT JOIN(SELECT S#, score score2 FROM SC WHERE C# = '02')c2 ON s.S#=c2.S#
    LEFT JOIN(SELECT S#, score score3 FROM SC WHERE C# = '03')c3 ON s.S#=c3.S#
    WHERE c1.score1>c2.score2

/*
如果考虑02课程没有成绩可以将最后一句改为
where c1.score1>c2.score2 or (c2.score2 is null and c1.score1 is not null)
*/

1.1 查询同时存在" 01 "课程和" 02 "课程的情况

按上述步骤做完1后1.1-1.3就比较简单了改一下where里的条件就搞定。

代码

SELECT s.*, c1.score1, c2.score2, c3.score3
    FROM Student s
    LEFT JOIN(SELECT S#, score score1 FROM SC WHERE C# = '01')c1 ON s.S#=c1.S#
    LEFT JOIN(SELECT S#, score score2 FROM SC WHERE C# = '02')c2 ON s.S#=c2.S#
    LEFT JOIN(SELECT S#, score score3 FROM SC WHERE C# = '03')c3 ON s.S#=c3.S#
    WHERE c2.score2 IS NOT NULL AND c1.score1 IS NOT NULL

1.2 查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null )

代码

SELECT s.*, c1.score1, c2.score2, c3.score3
    FROM Student s
    LEFT JOIN(SELECT S#, score score1 FROM SC WHERE C# = '01')c1 ON s.S#=c1.S#
    LEFT JOIN(SELECT S#, score score2 FROM SC WHERE C# = '02')c2 ON s.S#=c2.S#
    LEFT JOIN(SELECT S#, score score3 FROM SC WHERE C# = '03')c3 ON s.S#=c3.S#
    WHERE c1.score1 IS NOT NULL

1.3 查询不存在" 01 "课程但存在" 02 "课程的情况

代码

SELECT s.*, c1.score1, c2.score2, c3.score3
    FROM Student s
    LEFT JOIN(SELECT S#, score score1 FROM SC WHERE C# = '01')c1 ON s.S#=c1.S#
    LEFT JOIN(SELECT S#, score score2 FROM SC WHERE C# = '02')c2 ON s.S#=c2.S#
    LEFT JOIN(SELECT S#, score score3 FROM SC WHERE C# = '03')c3 ON s.S#=c3.S#
    WHERE c2.score2 IS NOT NULL AND c1.score1 IS NULL

2. 查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩

思路

平均成绩可以用avg()函数求得,因为是每个同学的平均成绩,所以用group by按学生编号进行分组。

因为需要查询学生姓名,所以求得平均成绩后需要连接学生信息表。在where处判断平均成绩是否大于等于60。

代码

SELECT s.Sname, c.*
    FROM
    (
        SELECT S#, AVG(score) avg_score
            FROM SC
            GROUP BY S#
    )c
    JOIN Student s ON c.S#=s.S#
    WHERE c.avg_score >= 60

3. 查询在 SC 表存在成绩的学生信息

思路

在该数据库中存在成绩就相当于存在数据(SC表中没有null),所以直接判断学生编号是否在SC表中出现过即可。

要求输出的是学生信息,所以输出Student表。使用where语句判断S#(学生编号)是否在SC中出现过。只用select不加distinct也可以得到一样的答案,但是不加distinct在数据量巨大的时候可能会导致运行时间显著增长,所以建议还是加上,养成良好的代码习惯Orz。

代码

SELECT *
    FROM Student s
    WHERE S# IN(SELECT DISTINCT S# FROM SC)

4. 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )

思路

需要查询选课数和总成绩,所以需要分组,然后又需要查询姓名,所以要和Student表连接。

这里有两种方法,可以先对SC表进行分组后连接Student,也可以先连接Student后分组。

先对SC表进行分组后连接Student会导致一些课程总数显示为null(显示为0更符合题意)。可以用is null()函数将null值置换为0。

先连接后分组则可能会报错(某些sql版本),因为学生姓名之类的信息既不是group by的key,也没有用聚合函数。一种解决方案是把姓名等也做为key。

代码

-- 方法1
SELECT s.*, ISNULL(c.count_courses,0) count_courses, c.sum_score
    FROM Student s
    LEFT JOIN
    (
        SELECT S#, COUNT(C#) count_courses, SUM(score) sum_score
            FROM SC
            GROUP BY S#
    )c ON s.S# = c.S#

-- 方法2
SELECT s.*, COUNT(C#) count_courses, SUM(score) sum_score
    FROM Student s
    LEFT JOIN SC c
        ON s.S#=c.S#
    GROUP BY s.S#,s.Sname,s.Sage,s.Ssex

4.1 查有成绩的学生信息

思路

似乎和Q3重复了,所以就当这里的信息是指Q4提到的信息。在Q4的基础上不用left join,改成inner join(inner可以省略)就可以只保留有成绩的学生了。

代码

SELECT s.*, count_courses, sum_score
    FROM Student s
    JOIN
    (
        SELECT S#, COUNT(C#) count_courses, SUM(score) sum_score
            FROM SC
            GROUP BY S#
    )c ON s.S# = c.S#

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

思路

老师相关的数据保存在Teacher表中,所以对该表进行操作即可。

查询的是数量所以用count()函数,条件为李姓,即名字字段第一个字符为李,用%通配符'李%'即可。

需要注意的是数据库中的字段值是unicode编码的(类型是nvarchar),所以需要加上N即N'李%'

代码

SELECT COUNT(T#) cnt_李
    FROM Teacher
    WHERE Tname LIKE N'李%'


登录后评论

共有0条评论