1. 程式人生 > >sql 經典查詢50題 思路(一)

sql 經典查詢50題 思路(一)

因為需要提高一下sql的查詢能力,當然最快的方式就是做一些實際的題目了。選擇了這個sql的50題,這次大概做了前10題左右,把思路放上來,也是一個總結。

具體題目見:

https://zhuanlan.zhihu.com/p/72223558

 

第一部分的題目主要使用的技術是連表查詢和子查詢,難倒不難,主要是要把思路轉換過來。

首先畫出一個各個表之間的關係圖(沒畫圖之前關係老是搞不清)

 

 

 1.查詢" 01 "課程比" 02 "課程成績高的學生的資訊及課程分數

學生的資訊在表1當中,課程成績在表4當中,當然要用到連表查詢。

這裡很有普遍性的一個問題是:要從表4中找出Sid相同,但是Cid為1的score大於Cid為2的score的記錄。這裡要使用子查詢,分別限定條件為Cid=‘1’,Cid='2',變成兩個表,再查滿足條件的就很簡單了。

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這個也是常用的思路,當要連線兩個某一列相關的表時。

 

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