1. 程式人生 > 實用技巧 >【DataBase】SQL50 Training 50題訓練

【DataBase】SQL50 Training 50題訓練

原文地址:

https://blog.csdn.net/xiushuiguande/article/details/79476964

實驗資料

CREATE DATABASE IF NOT EXISTS SQL50;
USE SQL50;

CREATE TABLE Student(sid VARCHAR(10),sname VARCHAR(10),sage DATETIME,ssex NVARCHAR(10)); INSERT INTO Student VALUES('01' , '趙雷' , '1990-01-01' , ''); INSERT INTO Student VALUES('02' , '錢電' , '
1990-12-21' , ''); INSERT INTO Student VALUES('03' , '孫風' , '1990-05-20' , ''); INSERT INTO Student VALUES('04' , '李雲' , '1990-08-06' , ''); INSERT INTO Student VALUES('05' , '周梅' , '1991-12-01' , ''); INSERT INTO Student VALUES('06' , '吳蘭' , '1992-03-01' , ''); INSERT INTO Student VALUES('07' , '鄭竹' , '1989-07-01
' , ''); INSERT INTO Student VALUES('08' , '王菊' , '1990-01-20' , '');

CREATE TABLE Course(cid VARCHAR(10),cname VARCHAR(10),tid VARCHAR(10)); INSERT INTO Course VALUES('01' , '語文' , '02'); INSERT INTO Course VALUES('02' , '數學' , '01'); INSERT INTO Course VALUES('03' , '英語' , '03');

CREATE TABLE Teacher(tid VARCHAR
(10),tname VARCHAR(10)); INSERT INTO Teacher VALUES('01' , '張三'); INSERT INTO Teacher VALUES('02' , '李四'); INSERT INTO Teacher VALUES('03' , '王五');

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);

4張表的結構關係

Course課程表:

  課程ID、課程名、教師ID

SC成績表:

  學生ID、課程ID、成績

Student學生表:

  學生ID、學生姓名、學生年齡、學生性別、

Teacher老師表:

  教師ID、教師名

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

先查詢 01課程的成績表 & 02課程的成績表

SELECT * FROM `sc` WHERE `cid` = 1;
SELECT * FROM `sc` WHERE `cid` = 2;

使用連線查詢,附加 01表的成績 > 02表的成績

SELECT 
    sc1.`sid`
FROM
    (SELECT `sid`,`cid`,`score` FROM `sc` WHERE `cid` = 1) AS sc1,
    (SELECT `sid`,`cid`,`score` FROM `sc` WHERE `cid` = 2) AS sc2
where
    sc1.`sid` = sc2.`sid`
    and
    sc1.`score` > sc2.`score`;

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

資訊都在成績表裡面,要每個學生的全部成績的平均成績,

使用AVG聚合函式,然後對學生ID進行分組GROUP BY

查出上面的結果之後再對平均分進行 > 60的篩選

但是為什麼SQL查不出結果???

SELECT 
    `sid`,AVG(`score`) AS 'avg_sc'
FROM 
    `sc`
GROUP BY 
    `sid`
HAVING    
    'avg_sc' > 60;

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

因為在成績表裡面,可以使用分組+計數+求和,求出成績表內的學號,選課數和總成績

然後再和學生表進行一個左連線,學生表作為主表,上面的結果表作為從表,因為還存在學生表沒有選課的情況

成績表的篩選

SELECT 
    `sid`,COUNT(`cid`) AS '選課數',SUM(`score`) as '總成績'
FROM
    `sc`
GROUP BY 
    `sid`;

左連線學生表

SELECT 
    S1.`sid`,S1.`sname`,S2.選課數,S2.總成績
FROM
    `student` AS S1
    LEFT JOIN (
    SELECT  `sid`,COUNT(`cid`) AS '選課數',SUM(`score`) AS '總成績'
    FROM `sc` 
   GROUP BY `sid`) AS S2 ON S1.`sid` = S2.`sid`;

4、查詢姓“李”的老師的個數

只在李老師表內查詢,使用計數函式

SELECT COUNT(*)
FROM `teacher`
WHERE `tname` LIKE '李%';

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

先篩選張三老師教授的課程ID,可以看到是01課程

SELECT `tid`
FROM `teacher`
WHERE `tname` = '張三';

通過上面的線索,查詢課程表,其對應的課程ID是02

select `cid` -- ,`cname`,`tid`
from `course`
where `tid` = (SELECT `tid` FROM `teacher` WHERE `tname` = '張三');

在成績表查詢沒學02課程太難排查了,所以反過來,我們查學了02的學生ID

-- 我們查詢學了該課程的學生ID
SELECT DISTINCT `sid`
FROM `sc`
WHERE `cid` = (SELECT `cid` FROM `course` WHERE `tid` = (SELECT `tid` FROM `teacher` WHERE `tname` = '張三'))

再用上面這張表連線學生表查詢【左連線】

SELECT 
    S1.`sid`,S1.`sname`
FROM
    `student` AS S1
    LEFT JOIN (SELECT DISTINCT `sid`
    FROM `sc`
    WHERE `cid` = (SELECT `cid` FROM `course` WHERE `tid` = (SELECT `tid` FROM `teacher` WHERE `tname` = '張三')))
    AS S2
ON
    S1.`sid` = S2.`sid`
WHERE
    S1.`sid` NOT IN(S2.`sid`);

6、查詢學過“```”並且也學過編號“```”課程的同學的學號、姓名;

7、查詢學過“張三”老師所教的所有課的同學的學號、姓名;

查詢張三老師的教師編號:

SELECT `tid` FROM `Teacher` WHERE `tname` = '張三'

然後根據編號查詢所授課程:

SELECT `cid`
FROM `Course`
WHERE `tid` = (SELECT `tid` FROM `Teacher` WHERE `tname` = '張三');

然後得到對應的所學課程的學生編號

SELECT `sid` 
FROM `SC`
WHERE `cid` IN(
    SELECT `cid` 
    FROM `Course` 
    WHERE `tid` = (
        SELECT `tid` 
        FROM `Teacher` 
        WHERE `tname` = '張三'
        )
    );

最後再聯合學生表:

SELECT `sid`,`sname`
FROM `Student`
WHERE `sid` IN (
    select `sid` 
    from `SC`
    where `cid` IN(
        SELECT `cid` 
        FROM `Course` 
        WHERE `tid` = (
            SELECT `tid` 
            FROM `Teacher` 
            WHERE `tname` = '張三'
        )
    )
);

8、查詢課程編號“01”的成績比課程編號“02”課程低的所有同學的學號、姓名;

9、查詢所有課程成績小於60分的同學的學號、姓名;

也就是說只要其中一個課程成績大於60就不算在內

所以就可以先查詢大於60分,再取反就行了

大於60分的學生ID:

SELECT `sid` FROM `SC` WHERE `score` > 60

然後取反得到:

SELECT `sid`,`sname`
FROM `Student`
WHERE `sid` NOT IN(SELECT `sid` FROM `SC` WHERE `score` > 60)

10、查詢沒有學全所有課的同學的學號、姓名;

首先是需要知道全部課程個數

然後這個查詢的意思是,計數學生學習課程的個數,如果小於總課數即沒學全

但是需要跟學生表關聯,他這裡的聯動真的難理解。。。

SELECT 
    `sid`,`sname` 
FROM 
    `Student`
WHERE 
    (SELECT COUNT(*) FROM `SC` WHERE `Student`.`sid` = `SC`.`sid`) < (SELECT COUNT(*) FROM `Course`)

11、查詢至少有一門課與學號為“01”的同學所學相同的同學的學號和姓名;

24、查詢學生平均成績及其名次

SELECT 
    a.sid,
    a.avg_score,
    SUM(CASE WHEN a.avg_score<b.avg_score THEN 1 ELSE 0 END)+1 scc
FROM 
    (SELECT sid,AVG(score) avg_score FROM SC GROUP BY sid) a INNER JOIN 
    (SELECT sid,AVG(score) avg_score FROM SC GROUP BY sid) b
GROUP BY 
    a.sid,
    a.avg_score
ORDER BY 
    scc

25、查詢各科成績前三名的記錄

26、查詢每門課程被選修的學生數

SELECT 
    `cid`,COUNT(`sid`) '人數'
FROM
    `sc`
GROUP BY
    `cid`

27、查詢出只選修了一門課程的全部學生的學號和姓名

# 查詢選課數只有1的學生編號
SELECT 
    `sid`,COUNT(`cid`) '選課數'
FROM 
    `sc`
GROUP BY
    `sid`
HAVING 
    `選課數` = 1
# 然後關聯學生表進行查詢
SELECT 
    `student`.`sname`,`ss`.`sid`
FROM
    `student`,
    (SELECT `sid`,COUNT(`cid`) '選課數'
    FROM `sc`
    GROUP BY `sid`
    HAVING `選課數` = 1) `ss`
WHERE
    `student`.`sid` IN (`ss`.`sid`)

28、查詢男生、女生人數

SELECT `ssex`,COUNT(1) '人數'
FROM `student`
GROUP BY `ssex`

29、查詢名字中含有"風"字的學生資訊

SELECT *
FROM `student`
WHERE `sname` LIKE '%風%';

30、查詢同名同姓學生名單,並統計同名人數

SELECT 
    `sname`,COUNT(1) AS '同名人數'
FROM
    `student`
GROUP BY
    `sname`
HAVING 
    `同名人數` > 1

30、查詢同名同性學生名單,並統計同名男生人數

SELECT 
    `sname`,`ssex`, COUNT(1) AS num 
FROM 
    Student
GROUP BY 
    `sname`,`ssex`
HAVING 
    COUNT(1) > 1 AND `ssex`=''

31、查詢1990年出生的學生名單(注:Student表中Sage列的型別是datetime)

SELECT * FROM `student` WHERE YEAR(`sage`) = 1990 ;

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

# 對課程編號分組,求平均分,然後分數升序排列,對課程編號降序排列
SELECT 
    `cid`,AVG(`score`)
FROM
    `sc`
GROUP BY 
    `cid`
ORDER BY
    `cid` DESC;

37、查詢不及格的課程,並按課程號從大到小排列

# 在成績表中的查詢    
SELECT * FROM `sc` WHERE `score` < 60 ORDER BY `cid` DESC;
# 關聯課程表
SELECT 
    `sc`.*, `course`.`cname`
FROM
    `sc`,`course`
WHERE
    `sc`.`cid` = `course`.`cid`
    AND `sc`.`score` < 60 ORDER BY `sc`.`cid` DESC

38、查詢課程編號為"01"且課程成績在60分以上的學生的學號和姓名;

# 1、現在成績表查詢課程編號為1的
SELECT * FROM `sc` WHERE `cid` = 01;
# 2、再新增分數要求大於60的
SELECT * FROM `sc` WHERE `cid` = 01 AND `score` > 60;
# 3、最後聯合學生表獲取名字
SELECT 
    `sc`.*,`student`.`sname`  
FROM 
    `sc`,`student`
WHERE 
    `sc`.`sid` = `student`.`sid`
    AND `sc`.`cid` = 01 
    AND `score` > 60

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

# 查詢老師編號
SELECT `tid` FROM `teacher` WHERE `tname` = '張三';
# 通過編號查詢所授課程編號
SELECT `cid` FROM `course` WHERE `tid` = (SELECT `tid` FROM `teacher` WHERE `tname` = '張三');
# 查詢到成績表學生編號和成績
SELECT `sid`,`score`
FROM `sc`
WHERE`cid` = (SELECT `cid` FROM `course` WHERE `tid` = (SELECT `tid` FROM `teacher` WHERE `tname` = '張三'))
ORDER BY `score` DESC 
LIMIT 1
# 關聯學生表
SELECT 
    `student`.`sname`,`ss`.`score`
FROM 
    `student`,
    (SELECT `sid`,`score`
    FROM `sc`
    WHERE`cid` = (SELECT `cid` FROM `course` WHERE `tid` = (SELECT `tid` FROM `teacher` WHERE `tname` = '張三'))
    ORDER BY `score` DESC 
    LIMIT 1) `ss`
WHERE
    `student`.`sid` = `ss`.`sid`

42、查詢每門功課成績最好的前兩名學生

43、統計每門課程的學生選修人數(超過5人的課程才統計)。

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

# 查詢成績表,按照課程欄位分組,計數整個表的記錄
# 要求課程大於5記錄的倒序排序,並返回人數記錄
SELECT cid,COUNT(1) COUNT
FROM SC GROUP BY cid HAVING COUNT(1)>=5 ORDER BY COUNT DESC,cid ;

44、檢索至少選修兩門課程的學生學號

# 查詢成績表,並計數課程欄位
# 對學號欄位分組,之後計數的課程欄位大於1的記錄返回
SELECT `sid`,COUNT(`cid`) AS C
FROM `sc`
GROUP BY `sid`
HAVING C > 1;

45、查詢選修了全部課程的學生資訊

# 1 先查詢課程表的總課程數量
SELECT COUNT(1) FROM Course
# 2 在成績表中,查詢選課累計等於總課程數的學生ID
SELECT sid ,COUNT(cid) count_c FROM SC 
GROUP BY sid 
HAVING count_c=(SELECT COUNT(1) FROM Course);
# 3 查詢學生表得到資訊
SELECT `student`.*
from 
    `student`,
    (SELECT sid ,COUNT(cid) count_c FROM SC 
    GROUP BY sid 
    HAVING count_c=(SELECT COUNT(1) FROM Course)) as t
WHERE
    `student`.`sid` in (t.`sid`)

46、查詢各學生的年齡

# 用當前日期求得年份值,再減去欄位日期的年份值即可
SELECT Student.*,YEAR(CURDATE())-YEAR(Student.sage) AS '年齡' FROM Student;

47、查詢本週過生日的學生

SELECT * FROM Student WHERE WEEKOFYEAR(NOW())-WEEKOFYEAR(sage)=0;

48、查詢下週過生日的學生

# 使用周按年換算函式,然後和月一樣,下一週就取-1
SELECT * FROM Student WHERE WEEKOFYEAR(NOW())-WEEKOFYEAR(sage)=-1;

49、查詢本月過生日的學生

# 先求出現在的時間的月,再和欄位月相減得為0的記錄即可
SELECT * FROM Student WHERE MONTH(NOW())-MONTH(sage)=0;

50、查詢下月過生日的學生

# 本月值,減去欄位月的值,相差一個月
# 因為本月大於欄位月相減求得的差一定是大於0的
# 所以要查出下一個月過生日的人應該為負數,例如下一個月就-1,下3個月就-3
SELECT * FROM Student WHERE MONTH(NOW())-MONTH(sage)=-1;