由于须要提升一下sql的查询能力,固然最快的方式就是作一些实际的题目了。选择了这个sql的50题,此次大概作了前10题左右,把思路放上来,也是一个总结。sql
具体题目见:spa
https://zhuanlan.zhihu.com/p/72223558code
第一部分的题目主要使用的技术是连表查询和子查询,难倒不难,主要是要把思路转换过来。blog
首先画出一个各个表之间的关系图(没画图以前关系总是搞不清)get
1.查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数class
学生的信息在表1当中,课程成绩在表4当中,固然要用到连表查询。效率
这里颇有广泛性的一个问题是:要从表4中找出Sid相同,可是Cid为1的score大于Cid为2的score的记录。这里要使用子查询,分别限定条件为Cid=‘1’,Cid='2',变成两个表,再查知足条件的就很简单了。select
select Student.SId,Student.Sname,Student.Sage,Student.Ssex,r.科目一成绩,r.科目二成绩 from study.dbo.Student right join (select t1.SId as 学生ID,t1.score as 科目一成绩,t2.score as 科目二成绩 from (select SId,score from study.dbo.SC where CId='01')as t1, (select SId,score from study.dbo.SC where CId='02')as t2 where t1.SId=t2.SId and t1.score>t2.score) as r on Student.SId=r.学生ID
join -- on这个也是经常使用的思路,当要链接两个某一列相关的表时。im
1.1查询存在" 01 "课程但可能不存在" 02 "课程的状况(不存在时显示为 null )技术
和第一题思路相似,注意以01课程为准,因此要用left join
select * from (select SId,score from study.dbo.SC where CId='01') as t1 left join (select SId,score from study.dbo.SC where CId='02') as t2 on t1.SId=t2.SId
1.2 查询同时存在01和02课程的状况
很简单,用inner join,求两表交集
select t1.SId,t1.score,t2.score from (select SId,score from study.dbo.SC where CId='01') as t1 inner join (select SId,score from study.dbo.SC where CId='02') as t2 on t1.SId=t2.SId
1.3查询选择了02课程但没有01课程的状况
个人思路是仍是用一个right join,而后判断NULL值,不知道会不会比not in效率高。
select t2.SId,t2.score from (select SId,score from study.dbo.SC where CId='01') as t1 right join (select SId,score from study.dbo.SC where CId='02') as t2 on t1.SId=t2.SId where t1.score is null
2.查询平均成绩大于等于 60 分的同窗的学生编号和学生姓名和平均成绩
确定要连表,有表一有表四。平均成绩涉及到group by,对平均成绩的限制涉及到having语句
select t1.SId,t1.avg_score,t2.Sname from ( select SId,AVG(score) as avg_score from study.dbo.SC group by SId having AVG(score)>60 ) as t1 inner join study.dbo.Student as t2 on t1.SId=t2.SId
3.查询在 SC 表存在成绩的学生信息
依然是连表查询,表一的sid等于表四的sid,去除重复值使用DISTINCT便可
select DISTINCT Student.SId,Student.Sname,Student.Sage,Student.Ssex from study.dbo.SC inner join Student on SC.SId=Student.SId
4.查询全部同窗的学生编号、学生姓名、选课总数、全部课程的总成绩(没成绩的显示为 null )
依然是连表查询,left join
select Student.*,t2.count_id,t2.avg_score from Student left join (select SId,count(CId) as count_id ,avg(score)as avg_score from study.dbo.SC group by SId) as t2 on Student.SId=t2.SId
4.1 查有成绩的学生信息
inner join,不赘述
select Student.*,t2.count_id,t2.avg_score from Student inner join (select SId,count(CId) as count_id ,avg(score)as avg_score from study.dbo.SC group by SId) as t2 on Student.SId=t2.SId
5.查询「李」姓老师的数量
最简单的一题,知道like这种模糊查询就行
select COUNT(*) from Teacher where Tname like '李%'
6.查询学过「张三」老师授课的同窗的信息
这个有意思,表明着从一张表跳到另外一张表找信息
第一个思路固然是用join,多个表一个一个on链接起来
select Student.* from (select tid from Teacher where Tname='张三') as t1 inner join Course on t1.tid=Course.TId inner join SC on Course.CId=SC.CId inner join Student on SC.SId=Student.SId
可是也有另外一种写法
select study.dbo.Student.* from teacher,study.dbo.Course ,study.dbo.student,study.dbo.sc where teacher.Tname='张三' and teacher.TId=Course.TId and Course.CId=sc.CId and sc.SId=student.SId
直接from多个表,在where里写=
我查了一下,其实这种方式是用了隐式的inner join,效率差别不大
7.查询没有学全全部课程的同窗的信息
查到没有学全全部课程同窗的sid很简单,在表4中查询。同窗的信息用inner join联表1查询实现。
SELECT * FROM study.dbo.Student as t1 inner join (select Student.SId from Student left join study.dbo.SC on Student.SId=SC.SId group by Student.SId having COUNT(SC.CId)!=(select count(*) from study.dbo.Course)) as t2 on t1.SId=t2.SId