50道SQL練習題及答案

網(wǎng)上流傳這這樣的50道練習題,以下是我的解法,僅供各位聯(lián)系和參考

數(shù)據(jù)表介紹

--1.學生表
Student(SId,Sname,Sage,Ssex)
--SId 學生編號,Sname 學生姓名,Sage 出生年月,Ssex 學生性別

--2.課程表
Course(CId,Cname,TId)
--CId 課程編號,Cname 課程名稱,TId 教師編號

--3.教師表
Teacher(TId,Tname)
--TId 教師編號,Tname 教師姓名

--4.成績表
SC(SId,CId,score)
--SId 學生編號,CId 課程編號,score 分數(shù)

學生表 Student

create table Student(SId varchar(10),Sname varchar(10),Sage datetime,Ssex varchar(10));
insert into Student values('01' , '趙雷' , '1990-01-01' , '男');
insert into Student values('02' , '錢電' , '1990-12-21' , '男');
insert into Student values('03' , '孫風' , '1990-12-20' , '男');
insert into Student values('04' , '李云' , '1990-12-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吳蘭' , '1992-01-01' , '女');
insert into Student values('07' , '鄭竹' , '1989-01-01' , '女');
insert into Student values('09' , '張三' , '2017-12-20' , '女');
insert into Student values('10' , '李四' , '2017-12-25' , '女');
insert into Student values('11' , '李四' , '2012-06-06' , '女');
insert into Student values('12' , '趙六' , '2013-06-13' , '女');
insert into Student values('13' , '孫七' , '2014-06-01' , '女');

科目表 Course

create table Course(CId varchar(10),Cname nvarchar(10),TId varchar(10));
insert into Course values('01' , '語文' , '02');
insert into Course values('02' , '數(shù)學' , '01');
insert into Course values('03' , '英語' , '03');

教師表 Teacher

create table Teacher(TId varchar(10),Tname varchar(10));
insert into Teacher values('01' , '張三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');

成績表 SC

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

練習題目

1. 查詢" 01 "課程比" 02 "課程成績高的學生的信息及課程分數(shù)

join課程1成績表和課程2成績表,然后對該表進行篩選

SELECT
    c.SId,
    d.Sname,
    d.Sage,
    d.Ssex,
    c.S_01,
    c.S_02
FROM
    (
        SELECT
            a.SId,
            a.score AS S_01,
            b.score AS S_02
        FROM
            (
                SELECT
                    *
                FROM
                    50exercises.sc
                WHERE
                    CId = 01
            ) AS a
        JOIN (
            SELECT
                *
            FROM
                50exercises.sc
            WHERE
                CId = 02
        ) AS b ON a.SId = b.SId
        WHERE
            a.score > b.score
    ) AS c
JOIN 50exercises.student AS d ON c.SId = d.SId

1.1. 查詢同時存在" 01 "課程和" 02 "課程的情況

解題思路 join課程1和課程2的兩張表

SELECT
    a.SId,
    a.score AS S_01,
    b.score AS S_02
FROM
    (
        SELECT
            *
        FROM
            50exercises.sc
        WHERE
            CId = 01
    ) AS a
JOIN (
    SELECT
        *
    FROM
        50exercises.sc
    WHERE
        CId = 02
) AS b ON a.SId = b.SId

1.2. 查詢存在" 01 "課程但可能不存在" 02 "課程的情況(不存在時顯示為 null )

left join課程1和課程2

SELECT
    a.SId,
    a.score AS S_01,
    b.score AS S_02
FROM
    (
        SELECT
            *
        FROM
            50exercises.sc
        WHERE
            CId = 01
    ) AS a
left JOIN (
    SELECT
        *
    FROM
        50exercises.sc
    WHERE
        CId = 02
) AS b ON a.SId = b.SId

1.3. 查詢不存在" 01 "課程但存在" 02 "課程的情況

與1.2思路相似,反之即可

SELECT
    a.SId,
    a.score AS S_02,
    b.score AS S_01
FROM
    (
        SELECT
            *
        FROM
            50exercises.sc
        WHERE
            CId = 02
    ) AS a
LEFT JOIN (
    SELECT
        *
    FROM
        50exercises.sc
    WHERE
        CId = 01
) AS b ON a.SId = b.SId
where b.score IS NULL

2. 查詢平均成績大于等于 60 分的同學的學生編號和學生姓名和平均成績

篩選出平均成績大于60分,和學生表Join

SELECT
    b.Sid,
    b.Sname,
    c.avg_s
FROM
    50exercises.student AS b
JOIN (
    SELECT
        a.SId,
        avg(a.score) AS avg_s
    FROM
        50exercises.sc AS a
    GROUP BY
        a.Sid
    HAVING
        avg(a.score) >= 60
) AS c ON b.SId = c.SId

3. 查詢在 SC 表存在成績的學生信息

找出SC表中的學生,然后join學生表

SELECT
    a.*
FROM
    50exercises.student AS a
JOIN (
    SELECT DISTINCT
        SId
    FROM
        50exercises.sc
) AS b ON a.SId = b.SId

4. 查詢所有同學的學生編號、學生姓名、選課總數(shù)、所有課程的總成績(沒成績的顯示為 null )

從學生表left join成績表

SELECT
    a.*, b.sum_s
FROM
    50exercises.student AS a
LEFT JOIN (
    SELECT
        SId,
        sum(score) AS sum_s
    FROM
        50exercises.sc
    GROUP BY
        SId
) AS b ON a.SId = b.SId

4.1 查有成績的學生信息

從成績表開始,然后匹配學生表即可

SELECT
    SId,
    sum(score) AS sum_s
FROM
    50exercises.sc
GROUP BY
    SId

5. 查詢「李」姓老師的數(shù)量

找到姓李的老師的表,然后count

SELECT
    count(1)
FROM
    50exercises.teacher
WHERE Tname LIKE '李%'

6. 查詢學過「張三」老師授課的同學的信息

先找出張三老師教的課,然后找到有這么課成績的學生,然后join學生表

SELECT
    *
FROM
    50exercises.student AS e
JOIN (
    SELECT
        c.SId
    FROM
        50exercises.sc AS c
    JOIN (
        SELECT
            a.CId
        FROM
            50exercises.course AS a
        JOIN (
            SELECT
                *
            FROM
                50exercises.teacher
            WHERE
                Tname = '張三'
        ) AS b ON a.TId = b.TId
    ) AS d ON c.CId = d.CId
) AS f ON e.SId = f.SId

7. 查詢沒有學全所有課程的同學的信息

解法1,由于CId是整數(shù),所以可以相加,那么只要找出不是6的或者為空的就可以

SELECT
    *
FROM
    student AS a
LEFT JOIN (
    SELECT
        SId,
        SUM(CId) AS sum_cid
    FROM
        sc
    GROUP BY
        SId
) AS b ON a.SId = b.SId
WHERE
    b.sum_cid <> 6
OR b.sum_cid IS NULL

標準解法,上過所有課的人,在sc表中出現(xiàn)的次數(shù)和課程表中課的數(shù)量相同,然后反選即可

SELECT
    *
FROM
    student
WHERE
    student.sid NOT IN (
        SELECT
            sc.sid
        FROM
            sc
        GROUP BY
            sc.sid
        HAVING
            count(sc.cid) = (SELECT count(cid) FROM course)
    )

8. 查詢至少有一門課與學號為" 01 "的同學所學相同的同學的信息

首先得到學號01的同學學過的課程

select `CId`
from `50exercises`.sc
where `SId`= 01

然后取出至少就是篩選課程在這個范圍內(nèi)的記錄,得到Sid

select distinct `SId`
from `50exercises`.sc
where `CId`in(
    select `CId`
    from `50exercises`.sc
    where `SId`= 01
    )

最后和信息表組合

select b.*
from
(
select distinct `SId`
from `50exercises`.sc
where `CId`in(
    select `CId`
    from `50exercises`.sc
    where `SId`= 01
    )
    ) as a
join `50exercises`.student as b
on a.SId = b.`SId`

9. 查詢和" 01 "號的同學學習的課程 完全相同的其他同學的信息

select c.*
from `50exercises`.sc as a
join `50exercises`.student as c 
on a.`SId`=c.`SId`
group by a.SId
having  group_concat(a.CId order by a.CId) = (
        select  group_concat(b.CId order by b.CId)
        from `50exercises`.sc as b
        where b.SId = "01"
        group by b.SId
        )

10. 查詢沒學過"張三"老師講授的任一門課程的學生姓名

select distinct d.`Sname`
from `50exercises`.teacher as a
join `50exercises`.course as b
on a.`TId`= b.`TId` and a.`Tname` != "張三"
join `50exercises`.sc as c 
on b.`CId` = c.`CId`
join `50exercises`.student as d
on c.`SId` =  d.`SId`

11. 查詢兩門及其以上不及格課程的同學的學號,姓名及其平均成績

select a.`SId`,
            b.`Sname`,
            avg(a.score) as avg_score,
            sum(if(a.score < 60,1,0)) as smark
from `50exercises`.sc as a
join `50exercises`.student as b 
on a.`SId` = b.`SId`
group by a.`SId`
having smark >=2

12. 檢索" 01 "課程分數(shù)小于 60,按分數(shù)降序排列的學生信息

SELECT
    *
FROM
    sc AS a
JOIN student AS b ON a.SId = b.SId
WHERE
    a.CId = "01"
AND a.score < 60
ORDER BY
    a.score DESC

13. 按平均成績從高到低顯示所有學生的所有課程的成績以及平均成績

SELECT
    *
FROM
    sc AS a
JOIN (
    SELECT
        Sid,
        avg(score) AS AVG_S
    FROM
        sc
    GROUP BY
        SId
) AS b ON a.SId = b.Sid
ORDER BY
    b.AVG_S DESC

14. 查詢各科成績最高分、最低分和平均分;以如下形式顯示:課程 ID,課程 name,最高分,最低分,平均分,及格率,中等率,優(yōu)良率,優(yōu)秀率;及格為>=60,中等為:70-80,優(yōu)良為:80-90,優(yōu)秀為:>=90;要求輸出課程號和選修人數(shù),查詢結(jié)果按人數(shù)降序排列,若人數(shù)相同,按課程號升序排列

SELECT
    b.Cname,
    b.CId,
    max(a.score) AS "最高分",
    min(a.score) AS "最低分",
    avg(a.score) AS "平均分",
    sum(

        IF (a.score >= 60 AND a.score < 70, 1, 0)
    ) / count(DISTINCT Sid) "及格率",
    sum(

        IF (a.score >= 70 AND a.score < 80, 1, 0)
    ) / count(DISTINCT Sid) "中等率",
    sum(

        IF (a.score >= 80 AND a.score < 90, 1, 0)
    ) / count(DISTINCT Sid) "優(yōu)良率",
    sum(IF(a.score >= 90, 1, 0)) / count(DISTINCT Sid) "優(yōu)秀率"
FROM
    sc AS a
JOIN course AS b ON a.CId = b.CId
GROUP BY
    CId

15. 按各科成績進行排序,并顯示排名, Score 重復時保留名次空缺

SELECT
    A.CId,
    A.SId,
    A.score,

IF (
    a.cid =@tmid ,@rank :=@rank + 1 ,@rank := 1
) AS rank ,@tmid := a.cid
FROM
    (SELECT * from SC order by cid asc,score DESC) AS A,
    (SELECT @rank := 0 ,@tmid := NULL) AS B

15.1 按各科成績進行排序,并顯示排名, Score 重復時合并名次

SELECT
    A.CId,
    A.SId,
    A.score,
    CASE
WHEN a.cid <> @tmid THEN
    @rank := 1
WHEN a.cid = @tmid
AND a.score <> @tscore THEN
    @rank :=@rank + 1
WHEN a.cid = @tmid
AND a.score = @tscore THEN
    @rank := @rank
ELSE @rank := 1
END AS rank,
 @tmid := a.cid,
 @tscore := a.score
FROM
    (
        SELECT
            *
        FROM
            SC
        ORDER BY
            cid ASC,
            score DESC
    ) AS A,
    (
        SELECT
            @rank := 1 ,@tmid := NULL ,@tscore := 0
    ) AS B 

16. 查詢學生的總成績,并進行排名,總分重復時保留名次空缺

看了下數(shù)據(jù),沒有總成績相同的學生,檢驗不出效果,所以改成用01課程來檢驗

SELECT
a.SId,
a.all_s,
CASE
WHEN a.all_s <> @tscore then @rank := @rank+1
ELSE @rank = @rank
END as rank,
@tscore := a.all_s
FROM
    (
        SELECT
            SId,
            sum(score) AS all_s
        FROM
            sc
        WHERE
            Cid = "01"
        GROUP BY
            SId
        ORDER BY
            all_s DESC
    ) AS a,
(SELECT @rank := 0 ,@tscore := 0) AS b

16.1 查詢學生的總成績,并進行排名,總分重復時不保留名次空缺

SELECT
a.SId,
a.all_s,
@rank := @rank+1 as rank
FROM
    (
        SELECT
            SId,
            sum(score) AS all_s
        FROM
            sc
        WHERE
            Cid = "01"
        GROUP BY
            SId
        ORDER BY
            all_s DESC
    ) AS a,
(SELECT @rank := 0 ) AS b

17. 統(tǒng)計各科成績各分數(shù)段人數(shù):課程編號,課程名稱,[100-85],[85-70],[70-60],[60-0] 及所占百分比

和14題相同

SELECT
    b.Cname,
    b.CId,
    sum(

        IF (a.score >= 0 AND a.score < 60, 1, 0)
    ) / count(DISTINCT Sid) "[0,60)",
    sum(

        IF (a.score >= 60 AND a.score < 70, 1, 0)
    ) / count(DISTINCT Sid) "[60,70)",
    sum(

        IF (a.score >= 70 AND a.score < 85, 1, 0)
    ) / count(DISTINCT Sid) "[70,85)",
    sum(IF(a.score >= 85, 1, 0)) / count(DISTINCT Sid) "[85,100]"
FROM
    sc AS a
JOIN course AS b ON a.CId = b.CId
GROUP BY
    CId

18. 查詢各科成績前三名的記錄

SELECT
    *
FROM
    sc
WHERE
    (
        SELECT
            count(*)
        FROM
            sc AS a
        WHERE
            sc.cid = a.cid
        AND sc.score < a.score
    ) < 3 ##是不是比自己大的有三條
ORDER BY
    cid ASC,
    sc.score DESC;

解法2

SELECT
    a.sid,
    a.cid,
    a.score
FROM
    sc a
LEFT JOIN sc b ON a.cid = b.cid
AND a.score < b.score
GROUP BY
    a.cid,
    a.sid
HAVING
    count(b.cid) < 3
ORDER BY
    a.cid;

19. 查詢每門課程被選修的學生數(shù)

SELECT
    CId,
    COUNT(DISTINCT SId) AS count_s
FROM
    SC
GROUP BY
    CId

20. 查詢出只選修兩門課程的學生學號和姓名

SELECT
    *
FROM
    (
        SELECT
            SId,
            COUNT(DISTINCT CId) AS count_C
        FROM
            SC
        GROUP BY
            SId
        HAVING
            count_C <= 2
    ) AS a
JOIN student AS b ON a.SId = b.SId

21. 查詢男生、女生人數(shù)

SELECT
    Ssex,
    COUNT(DISTINCT SId) as Qty
FROM
    student
GROUP BY
    Ssex

22. 查詢名字中含有「風」字的學生信息

SELECT
    *
FROM
    student
WHERE
    sname LIKE "%風%"

23. 查詢同名同性學生名單,并統(tǒng)計同名人數(shù)

SELECT
    sname,
    COUNT(DISTINCT sid) AS Qty
FROM
    student
GROUP BY
    Sname
HAVING
    qty > 1

24. 查詢 1990 年出生的學生名單

SELECT
    *
FROM
    student
WHERE
    YEAR (Sage) = 1990

25. 查詢每門課程的平均成績,結(jié)果按平均成績降序排列,平均成績相同時,按課程編號升序排列

SELECT
    CId,
    avg(score) AS avg_s
FROM
    sc
GROUP BY
    CId
ORDER BY
    avg_s DESC,
    CId ASC

26. 查詢平均成績大于等于 85 的所有學生的學號、姓名和平均成績

SELECT
    a.SId,
    a.Sname,
    b.avg_s
FROM
    student AS a
JOIN (
    SELECT
        SId,
        avg(score) AS avg_s
    FROM
        sc
    GROUP BY
        SId
) AS b ON a.SId = b.SId

27. 查詢課程名稱為「數(shù)學」,且分數(shù)低于 60 的學生姓名和分數(shù)

SELECT
    c.Sname,
    d.score
FROM
    (
        SELECT
            a.SId,
            a.score
        FROM
            sc AS a
        JOIN course AS b ON a.CId = b.CId
        WHERE
            a.score < 60
        AND b.Cname = '數(shù)學'
    ) AS d
JOIN student AS c ON c.SId = d.SId

28. 查詢所有學生的課程及分數(shù)情況(存在學生沒成績,沒選課的情況)

SELECT
    *
FROM
    student AS a
JOIN course AS b
LEFT JOIN sc AS c ON a.SId = c.SId
AND b.CId = c.CId

29. 查詢?nèi)魏我婚T課程成績在 70 分以上的姓名、課程名稱和分數(shù)

SELECT
    *
FROM
    student AS a
JOIN course AS b
LEFT JOIN sc AS c ON a.SId = c.SId
AND b.CId = c.CId
where score > 70

30. 查詢不及格的課程

SELECT 
    DISTINCT cid
FROM
    sc
WHERE
    score < 60

31. 查詢課程編號為 01 且課程成績在 80 分以上的學生的學號和姓名

SELECT
    b.*
FROM
    (
        SELECT DISTINCT
            Sid
        FROM
            sc
        WHERE
            score >= 80
        AND Cid = '01'
    ) AS a
JOIN student AS b ON a.Sid = b.Sid

32. 求每門課程的學生人數(shù)

SELECT
    cid,
    COUNT(DISTINCT sid)
FROM
    sc
GROUP BY
    CId

33. 成績不重復,查詢選修「張三」老師所授課程的學生中,成績最高的學生信息及其成績

SELECT
    *
FROM
    teacher AS a
JOIN course AS b ON a.TId = b.TId
AND a.Tname = '張三'
JOIN sc AS c ON b.CId = c.CId
JOIN student AS d ON d.SId = c.SId
HAVING
    max(c.score)

34. 成績有重復的情況下,查詢選修「張三」老師所授課程的學生中,成績最高的學生信息及其成績

SELECT
    *
FROM
    teacher AS a
JOIN course AS b ON a.TId = b.TId
AND a.Tname = '張三'
JOIN sc AS c ON b.CId = c.CId
JOIN student AS d ON d.SId = c.SId
WHERE
    c.score = (
        SELECT
            max(c.score)
        FROM
            teacher AS a
        JOIN course AS b ON a.TId = b.TId
        AND a.Tname = '張三'
        JOIN sc AS c ON b.CId = c.CId
        JOIN student AS d ON d.SId = c.SId
    )

35. 查詢不同課程成績相同的學生的學生編號、課程編號、學生成績

SELECT
    a.cid,
    a.sid,
    a.score
FROM
    sc AS a
INNER JOIN sc AS b ON a.sid = b.sid
AND a.cid != b.cid
AND a.score = b.score
GROUP BY
    cid,
    sid

36. 查詢每門功成績最好的前兩名

SELECT
    *
FROM
    sc
WHERE
    (
        SELECT
            count(*)
        FROM
            sc AS a
        WHERE
            sc.cid = a.cid
        AND sc.score < a.score
    ) < 3 ##是不是比自己大的有三條
ORDER BY
    cid ASC,
    sc.score DESC;

37. 統(tǒng)計每門課程的學生選修人數(shù)(超過 5 人的課程才統(tǒng)計)

SELECT
    CId,
    COUNT(DISTINCT SId) AS Qty
FROM
    sc
GROUP BY
    CId
HAVING
    Qty > 5

38. 檢索至少選修兩門課程的學生學號

SELECT
    SId,
    COUNT(DISTINCT CId) AS Qty
FROM
    sc
GROUP BY
    SId
HAVING
    Qty >= 2

39. 查詢選修了全部課程的學生信息

SELECT
    b.*, COUNT(DISTINCT a.CId) AS Qty
FROM
    sc AS a
JOIN student AS b ON a.SId = b.SId
GROUP BY
    SId
HAVING
    Qty = (
        SELECT
            COUNT(DISTINCT CId)
        FROM
            course
    )

40. 查詢各學生的年齡,只按年份來算

SELECT
    *, YEAR (NOW()) - YEAR (Sage) + 1 AS Age
FROM
    student

41. 按照出生日期來算,當前月日 < 出生年月的月日則,年齡減一

SELECT
    *, TIMESTAMPDIFF(YEAR, Sage, NOW()) AS Age
FROM
    student

42. 查詢本周過生日的學生

SELECT
    *
FROM
    student
WHERE
    WEEKOFYEAR(Sage) = WEEKOFYEAR(NOW())

43. 查詢下周過生日的學生

SELECT
    *
FROM
    student
WHERE
    WEEKOFYEAR(Sage) = WEEKOFYEAR(NOW())+1

44. 查詢本月過生日的學生

SELECT
    *
FROM
    student
WHERE
    MONTH(Sage) = MONTH(NOW())

45. 查詢下月過生日的學生

SELECT
    *
FROM
    student
WHERE
    MONTH(Sage) = MONTH(NOW())+1
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容