SQL總結(七)查詢實戰


SQL總結(七)查詢實戰

一、場景

給定一個場景,學生選課系統為例,大家很熟悉。

主要關系:

學生(學號、姓名、年齡、性別)

教師(教師ID,教師姓名)

課程(課程ID,課程名稱,任教教師ID)

成績(學生ID,課程ID,成績)

二、創建表並預置數據

創建關系表:

--學生:Student(SID,SName,SAge,SSex)
--學生表(學號、姓名、年齡、性別)
--性別,0表示男,1表示女
--
--IF EXISTS(SELECT OBJECT_ID('Student')) /*此處永遠為true,原因是OBJECT_ID返回具體ID,或者NULL*/
--使用下列語句,如果沒有,什么都不返回,也就不存在
IF EXISTS(SELECT id FROM sysobjects WHERE name='Student') 
   DROP Table Student

Create table Student
(
    SID nvarchar(20) primary key not null,
    SName nvarchar(20),
    SAge int,
    SSex bit
)


--教師:Teacher(TID,TName)
--教師表(教師ID,教師姓名)
IF EXISTS(SELECT id FROM sysobjects WHERE name='Teacher') 
Drop table Teacher 
GO

Create table Teacher
(
    TID nvarchar(20) primary key not null,
    TName nvarchar(20) not null,    
)

--課程:Course(CID,CName,TID)
--課程表(課程ID,課程名稱,任教教師ID)
IF EXISTS(SELECT id FROM sysobjects WHERE name='Course') 
BEGIN 
   DROP Table Course
END
Create table Course
(
    CID  nvarchar(20)  primary key not null,
    CName nvarchar(50) not null,
    TID nvarchar(20)
)

IF EXISTS(SELECT id FROM sysobjects WHERE name='SC') 
DROP TABLE SC

--成績:SC(SID,CID,Score)
--成績表(學生ID,課程ID,成績)
Create table SC
(
    SID nvarchar(20) not null,
    CID nvarchar(20) not null,
    Score int
)
alter table SC add constraint PK_SC primary key(SID,CID)

預置數據

這里僅僅是個例子,針對不同的題目,可以預置適當的數據進行檢測。

/*預置數據*/
DELETE FROM Student
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S001','Tom','20','0')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S002','Lucy','21','1')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S003','Jim','18','0')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S004','Brush','20','0')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S005','Kim','22','1')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S006','Fka','20','0')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S007','Cidy','17','1')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S008','YouNi','19','0')
GO

DELETE FROM Teacher
INSERT INTO Teacher(TID,TName) VALUES('T001','張三')
INSERT INTO Teacher(TID,TName) VALUES('T002','李四')
INSERT INTO Teacher(TID,TName) VALUES('T003','王五')
GO

DELETE FROM Course
INSERT INTO Course(CID,CName,TID) VALUES('C01','英語','T001')
INSERT INTO Course(CID,CName,TID) VALUES('C02','體育','T002')
INSERT INTO Course(CID,CName,TID) VALUES('C03','數學','T003')
GO

DELETE FROM SC
INSERT INTO SC(SID,CID,Score) VALUES('S001','C01','78')
INSERT INTO SC(SID,CID,Score) VALUES('S001','C02','60')
INSERT INTO SC(SID,CID,Score) VALUES('S001','C03','97')
INSERT INTO SC(SID,CID,Score) VALUES('S002','C01','56')
INSERT INTO SC(SID,CID,Score) VALUES('S003','C01','55')
INSERT INTO SC(SID,CID,Score) VALUES('S004','C01','55')
GO
View Code

三、具體題目

以下題目,希望是一種練習題,是對具體SQL查詢方法的具體應用。對於一些復雜查詢,也進行分步求解,希望不只是明白了一道題的解法,培養一種解題思路。

以后遇到類似的問題就能輕易破解。

答案默認隱藏,意在希望讀者在思考之后,再看參考答案。

當然參考答案也不一定完全正確,或許還有更優解,如果你發現了,請提出。

 

1、查詢“C01”課程比“C02”課程成績高的所有學生的學號

--1) 最笨的方法
--分別得到C01成績單和C02課程的成績單,然后再得到C01課程比C02課程高的學生學號
SELECT SID,Score FROM SC WHERE CID='C01' 

SELECT SID,Score FROM SC WHERE CID='C02' 

SELECT A.SID FROM 
(SELECT SID,Score FROM SC WHERE CID='C01') AS A
INNER JOIN
(SELECT SID,Score FROM SC WHERE CID='C02') AS B
ON A.SID = B.SID WHERE A.Score>B.Score
點擊查看,參考答案

2、查詢平均成績大於60分的同學的學號和平均成績

SELECT SID,AVG(Score) AS ScoreAverage FROM SC GROUP BY SID HAVING AVG(Score)>60 
點擊查看,參考答案

3、查詢所有同學的學號、姓名、選課數、總成績

--1)通過Group查詢總成績和選課數,然后再聯表查詢
SELECT SID,COUNT(CID) AS CourseCount,SUM(Score) as SumScore FROM SC GROUP BY SID

SELECT Student.SID,SName,CourseCount,SumScore FROM Student 
LEFT JOIN 
(SELECT SID,COUNT(CID) AS CourseCount,SUM(Score) as SumScore FROM SC GROUP BY SID) AS B 
ON Student.SID = B.SID

--2)聯表查詢后再GROUP By
SELECT Student.SID,Student.Sname,COUNT(SC.CID),SUM(Score)
FROM Student LEFT OUTER JOIN SC ON Student.SID=SC.SID
GROUP BY Student.SID,Sname
參考答案

4、查詢姓“李”的老師的個數,不能重復

SELECT COUNT(DISTINCT(TID)) FROM Teacher WHERE TName LIKE '李%'
參考答案

5、查詢沒學過“張三”老師課的同學的學號、姓名 

--1)查詢沒有學過“張三”老師課的同學的學號,然后再查詢得到學生姓名
SELECT SID FROM SC 
LEFT JOIN Course ON SC.CID = Course.CID 
LEFT JOIN Teacher ON Course.TID = Teacher.TID WHERE Tname ='張三'

SELECT SID,Sname FROM Student WHERE SID NOT IN (SELECT SID FROM SC 
LEFT JOIN Course ON SC.CID = Course.CID 
LEFT JOIN Teacher ON Course.TID = Teacher.TID WHERE Tname ='張三')

--2)先查詢張三老師的所有課程,然后查詢選擇了張三老師課程的學生ID,最后查詢未選其課程的學生信息
SELECT CID FROM Course INNER JOIN Teacher ON Course.TID = Teacher.TID WHERE Teacher.TName='張三'

SELECT SID FROM SC LEFT JOIN 
(SELECT CID FROM Course INNER JOIN Teacher ON Course.TID = Teacher.TID WHERE Teacher.TName='張三') AS TeacherCID 
ON SC.CID = TeacherCID.CID

SELECT SID,SName FROM Student WHERE SID NOT IN
(
SELECT SID FROM SC LEFT JOIN 
(SELECT CID FROM Course INNER JOIN Teacher ON Course.TID = Teacher.TID WHERE Teacher.TName='張三') AS TeacherCID 
ON SC.CID = TeacherCID.CID
)

--3)查詢多表,獲取張三老師的課程
SELECT Student.SID,Student.SName FROM Student 
WHERE SID NOT IN 
(SELECT DISTINCT(SC.SID) FROM SC,Course,Teacher WHERE  SC.CID=Course.CID and Teacher.TID=Course.TID and Teacher.Tname='張三')
參考答案

6、查詢兩門以上不及格課程的同學的學號及其平均成績

--1)查詢有課程不及格的學生ID
SELECT DISTINCT(SID) FROM SC WHERE Score<60
SELECT SID,AVG(Score) AS ScoreAverage FROM SC GROUP BY SID HAVING  COUNT(SID)>2  AND SID IN (SELECT DISTINCT(SID) FROM SC WHERE Score<60)


--2)查詢有兩門以上不及格的學號
SELECT SID FROM SC WHERE Score<60 GROUP BY SID HAVING COUNT(SID)>2

SELECT SID,AVG(ISNULL(Score,0)) FROM SC 
WHERE SID IN (SELECT SID FROM SC WHERE Score<60 GROUP BY SID HAVING COUNT(SID)>2)
GROUP BY SID
參考答案

7、查詢全部學生都選修的課程的課程號和課程名

--查詢各個課程的學生總數
SELECT CID,COUNT(DISTINCT(SID)) AS SCount FROM SC GROUP BY CID
--查詢學生的總數
SELECT COUNT(DISTINCT(SID)) AS SCount FROM Student

--得到結果
SELECT CID,CName FROM Course 
WHERE CID IN (SELECT CID FROM SC GROUP BY CID 
HAVING COUNT(DISTINCT(SID))=(SELECT COUNT(DISTINCT(SID)) AS SCount FROM Student))
參考答案

8、統計每門課程的學生選修人數(超過10人的課程才統計)

要求輸出課程號和選修人數,查詢結果按人數降序排列,查詢結果按人數降序排列,若人數相同,按課程號升序排列 

SELECT CID,COUNT(SID) FROM SC GROUP BY CID HAVING COUNT(SID)>10 ORDER BY COUNT(SID) DESC,CID
參考答案

9、查詢每門功成績最好的前三名,要求輸出課程ID、前三名學號以及成績,並且按照課程號升序排列,同課程的成績倒敘排列

--1)取前三名
--查詢一門課的前三名
SELECT TOP 3 CID,SID,Score FROM SC WHERE CID='C01' ORDER BY Score DESC

--查詢每門課的前三名
SELECT CID,SID,Score FROM SC AS A 
WHERE SID IN (SELECT  TOP 3 SID FROM SC WHERE CID=A.CID ORDER BY Score DESC)
ORDER BY CID,Score DESC
參考答案1

如果成績有並列現象

--2)按分數取前三名,可以並列
--如果有並列分數就有問題了,可能前三名不止3人,應該按分數處理
SELECT CID,SID,Score FROM SC AS A
WHERE Score IN (SELECT TOP 3 Score FROM SC WHERE CID=A.CID ORDER BY Score DESC)
ORDER BY CID,Score DESC
參考答案2

加上排名

--3)相比第二種方法更合理,再深入一下,查詢結果加上排名
SELECT CID,SID,Score,Place=(SELECT COUNT(Score) FROM SC AS B WHERE B.CID=A.CID AND B.Score>A.Score)+1 FROM SC AS A
WHERE Score IN (SELECT TOP 3 Score FROM SC WHERE CID=A.CID ORDER BY Score DESC)
ORDER BY CID,Score DESC
參考答案3

10、查詢選修“張三老師所授課程的學生中,成績最高的學生姓名及其成績

--(1)根據教師姓名查詢其所授課程ID   
SELECT CID FROM Course WHERE Course.TID IN (SELECT TID FROM Teacher WHERE Teacher.TName='張三')
--(2)查詢一門課的最高成績           
SELECT TOP 1 Score FROM SC WHERE CID='C01' ORDER BY Score DESC
--(3)查詢所有課程中成績最高的學生ID,成績   
SELECT SID,CID,Score FROM SC AS A WHERE A.Score IN (SELECT TOP 1 Score FROM SC AS B WHERE A.CID=B.CID ORDER BY B.Score DESC)
--(4)查詢張三教師所授課程的成績最高的學生ID\成績, 
SELECT SID,CID,Score FROM SC AS A WHERE A.CID IN(SELECT CID FROM Course WHERE Course.TID IN (SELECT TID FROM Teacher WHERE Teacher.TName='張三')) AND A.Score IN (SELECT TOP 1 Score FROM SC AS B WHERE A.CID=B.CID ORDER BY B.Score DESC)
--(5)查詢學生姓名和成績
SELECT A.SID,Student.SName,Score FROM SC AS A 
LEFT JOIN Student ON A.SID = Student.SID 
WHERE A.CID IN(SELECT CID FROM Course WHERE Course.TID IN (SELECT TID FROM Teacher WHERE Teacher.TName='張三')) 
AND A.Score IN (SELECT TOP 1 Score FROM SC AS B WHERE A.CID=B.CID ORDER BY B.Score DESC)
--(6)查詢優化
參考答案

11、查詢每門課程的平均成績,結果按平均成績降序排列,平均成績相同時,按課程號升序排列

SELECT CID,AVG(Score) FROM SC GROUP BY CID ORDER BY AVG(Score) DESC,CID
參考答案

12、查詢學生總成績以及名次

--(1)查詢學生總成績
SELECT SID,SUM(Score) FROM SC GROUP BY SID

--(2)查詢總排名
SELECT SID,TotalScore,
Place=(SELECT COUNT(DISTINCT(TotalScore)) FROM (SELECT SID,SUM(Score) AS TotalScore FROM SC GROUP BY SID) AS T1 WHERE T1.TotalScore> T2.TotalScore) +1 
FROM (SELECT SID,SUM(Score) AS TotalScore FROM SC GROUP BY SID) AS T2
ORDER BY Place,SID
參考答案1

如果有的學生未選課怎么辦

--2)需要查詢所有學生的排名,有的學生沒有選課,成績為0

SELECT SID,TotalScore,
Place=(SELECT COUNT(DISTINCT(TotalScore)) FROM (SELECT SID,SUM(Score) AS TotalScore FROM SC GROUP BY SID) AS T1 WHERE T1.TotalScore> T3.TotalScore) +1 
FROM (SELECT Student.SID,Student.SName,ISNULL(TotalScore,0) AS TotalScore  FROM Student LEFT JOIN (SELECT SID,SUM(Score) AS TotalScore FROM SC GROUP BY SID) AS T2 ON Student.SID = T2.SID) AS T3
ORDER BY Place,SID
參考答案

13、統計各科成績,各分數段人數,結果包括:課程ID,課程名稱,[100-85],[85-70],[70-60],[ <60]

SELECT SC.CID AS 課程ID,CName AS 課程名稱
        ,SUM(CASE WHEN Score BETWEEN 85 AND 100 THEN 1 ELSE 0 END) AS [100 - 85]
        ,SUM(CASE WHEN Score BETWEEN 70 AND 85 THEN 1 ELSE 0 END) AS [85 - 70]
        ,SUM(CASE WHEN Score BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS [70 - 60]
        ,SUM(CASE WHEN Score < 60 THEN 1 ELSE 0 END) AS [60 -]
FROM SC,Course
where SC.CID=Course.CID
GROUP BY SC.CID,Cname
參考答案

14、查詢各科的及格率

SELECT CID,
      SUM(CASE WHEN Score>=60 THEN 1 ELSE 0 END) AS Pass,
      SUM(CASE WHEN Score<60 THEN 1 ELSE 0 END) AS Fail 
FROM SC GROUP BY CID

--2)再查詢及格率
SELECT CID,Pass/(Pass + Fail) FROM 
(
SELECT CID,
      SUM(CASE WHEN Score>=60 THEN 1 ELSE 0 END) AS Pass,
      SUM(CASE WHEN Score<60 THEN 1 ELSE 0 END) AS Fail 
FROM SC GROUP BY CID
) AS T1
參考答案

15、求各科成績的最高分和最低分

SELECT CID,MAX(Score),MIN(Score) FROM SC GROUP BY CID
參考答案

16、查詢出生1990年之前的學生名單

SELECT  DATEPART(YEAR,SAge),* FROM Student WHERE DATEPART(YEAR,GETDATE())-SAge < 1990
參考答案

17、查詢選課少於兩門課程的學生名單

--1)以下結果錯誤,還有沒選課的學生
SELECT SID,SName FROM Student WHERE SID IN (
SELECT SID FROM SC GROUP BY SID HAVING COUNT(CID)<2)

--2)用其否定,NOT IN
SELECT SID,SName FROM Student  WHERE SID NOT IN (
SELECT SID FROM SC GROUP BY SID HAVING COUNT(CID)>=2)
參考答案

18、查詢英語成績第三名的學生成績單 

--1)查詢英語課程ID
SELECT CID FROM Course WHERE CName='英語'
--2)查詢英語所有成績
SELECT DISTINCT Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英語')
--3)查詢前三名成績
SELECT DISTINCT TOP 3 Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英語') ORDER BY Score ASC
--4)查詢第三名成績
SELECT TOP 1 Score FROM (SELECT DISTINCT TOP 3 Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英語') ORDER BY Score ASC) AS TopThree

--5)查詢學生ID
SELECT SID FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英語') AND Score= (SELECT TOP 1 Score FROM (SELECT DISTINCT TOP 3 Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英語') ORDER BY Score ASC) AS TopThree)

--6)查詢學生成績單
SELECT SID,CID,Score FROM SC WHERE SID IN (
SELECT SID FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英語') AND Score= (SELECT TOP 1 Score FROM (SELECT DISTINCT TOP 3 Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英語') ORDER BY Score ASC) AS TopThree)
)
查看答案

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM