2020-09-20 MySql经典45题

-- 1.查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数

-- 此题思路需要建立一张同时具有Student信息和2个SC信息的表,及3张小表要join起来;

-- 同时,inner join 或者 left join,抑或都可,逻辑要清楚。

SELECT

*

FROM

Student stu

INNER JOIN SC a ON stu.SId = a.SId

INNER JOIN SC b ON stu.SId = b.SId

WHERE

a.cid = '01'

AND b.CId = '02'

AND a.score > b.score;

-- 第1题扩展,理解不同join类型下,例如inner join/left join,使用筛选条件,放在on后面与放在where后面的区别。

SELECT

*

FROM

SC a

LEFT JOIN SC b ON a.Sid = b.Sid

AND b.Cid = "02"

AND a.CId = "01"; 

区别于

SELECT

*

FROM

SC a

LEFT JOIN SC b ON a.Sid = b.Sid

AND b.Cid = "02"

WHERE

a.CId = "01";

-- 2.查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩

-- Solution A:

SELECT

a.SId,

b.Sname,

AVG(score)

FROM

SC a

LEFT JOIN Student b ON a.SId = b.SId

GROUP BY

a.SId,

b.Sname

HAVING

AVG(score) >= 60;

-- Solution B:

SELECT

a.SId,

a.Sname,

b.avg_score

FROM

Student a

INNER JOIN (

SELECT

SId,

AVG(Score) AS avg_score

FROM

SC

GROUP BY

SId

HAVING

avg_score >= 60

) b

WHERE

a.SId = b.SId;

-- 3.查询在 SC 表存在成绩的学生信息

SELECT DISTINCT

a.*

FROM

Student a

INNER JOIN SC b ON a.SId = b.SId

WHERE

b.Score IS NOT NULL;

# Group by语法:只能查询分组字段,其他字段要以聚合函数的形式被查询出来

# select b.* from SC a left join Student b on a.SId=b.SId GROUP BY b.SId; #这种语法会报错

# select b.Sid, GROUP_CONCAT(Sname) from SC a left join Student b on a.SId=b.SId GROUP BY b.SId; #此条可以运行

# 可以通过子查询克服group by的语法限制。

SELECT

b.*

FROM

(SELECT SId FROM SC GROUP BY SId) a

LEFT JOIN Student b ON a.Sid = b.Sid;

-- 4.查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为null)

SELECT

a.SId,

a.Sname,

b.count_course,

b.total_score

FROM

Student a

LEFT JOIN (

SELECT

SId,

COUNT(CId) AS count_course,

SUM(Score) AS total_score

FROM

SC

GROUP BY

SId

) b ON a.SId = b.SId;

SELECT

a.SId,

Sname,

COUNT(CId),

SUM(score)

FROM

Student a

LEFT JOIN SC b ON a.SId = b.SId

GROUP BY

a.SId,

  Sname;

-- 5.查询「李」姓老师的数量

SELECT

COUNT(*)

FROM

Teacher

WHERE

Tname LIKE "李%";

-- 6.查询学过「张三」老师授课的同学的信息

SELECT

stu.*, Tname

FROM

Teacher t

INNER JOIN Course c ON t.TId = c.TId

INNER JOIN SC s ON s.CId = c.CId

INNER JOIN Student stu ON stu.SId = s.SId

WHERE

t.Tname = "张三";

-- 7.查询没有学全所有课程的同学的信息

-- 我本人思路,先找出学全了所有课程的同学SId

SELECT

*

FROM

Student

WHERE

Sid NOT IN (

SELECT

SId

FROM

SC

GROUP BY

SId

HAVING

count(SC.CId) = (select count(*) from Course)

);

-- 以下是数据蛙思路,貌似只是从SC里有记录的学生开始查,而不是从所有学生里那里查。所以我个人的答案得出的结果,会包括没有修任何课程的学生

/* SELECT

a.*, COUNT(CId) AS c_count

FROM

Student a

INNER JOIN SC b ON a.SId = b.SId

GROUP BY

a.SId

HAVING

c_count < (SELECT count(CId) FROM Course); */  #此须代码又不符合group by 分组语法

SELECT

a.*, b.c_count

FROM

Student a

INNER JOIN (

SELECT

SId,

COUNT(CId) AS c_count

FROM

SC

GROUP BY

SId

HAVING

c_count < (SELECT count(CId) FROM Course)

) b ON a.SId = b.SId;

-- 8.查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息

SELECT

*

FROM

Student

WHERE

SId IN (

SELECT DISTINCT

SId

FROM

SC

WHERE

CId IN (

SELECT

CId

FROM

SC

WHERE

SId = '01'

)

)

AND Student.SId != '01';

-- 9.查询和" 01 "号的同学学习的课程完全相同的其他同学的信息

/*第一种思路:先找出01号同学所学的课程,然后找出学习了01所学课程以外课程的同学,进行Not挑选,这样挑选出的同学,学的都是01所学课程内的课程。

此时才可以进行count计数,所学课程与01所学课程数目一样的,即为我们查询的目标。*/

SELECT

a.*

FROM

Student a

INNER JOIN (

SELECT

SId

FROM

SC

WHERE

SId NOT IN (

SELECT

SId

FROM

SC

WHERE

CId NOT IN (

SELECT

CId

FROM

SC

WHERE

SId = '01'

)

)

AND SId != '01'

GROUP BY

SId

HAVING

COUNT(CId) = (

SELECT

COUNT(*)

FROM

SC

WHERE

SId = '01'

)

) b ON b.SId = a.SId;

/*方法二:直接找出和01号修的课一模一样的学生,用到group_concat*/

SELECT

c.*

FROM

Student c

INNER JOIN (

SELECT

SId,

GROUP_CONCAT(CId ORDER BY CId ASC) as courses

FROM

SC

GROUP BY

SId

) a ON c.Sid = a.Sid

INNER JOIN (

SELECT

SId,

GROUP_CONCAT(CId ORDER BY CId ASC) as courses

FROM

SC

GROUP BY

SId

HAVING

SId = '01'

) b ON a.courses=b.courses and c.SId!='01';

-- 10.查询没学过"张三"老师讲授的任一门课程的学生姓名

SELECT

Sname

FROM

Student

WHERE

SId NOT IN (

SELECT

SId

FROM

SC

WHERE

CId IN (

SELECT

CId

FROM

Course

INNER JOIN Teacher ON Course.TId = Teacher.TId

WHERE

Tname = '张三'

)

)

-- 11.查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

SELECT

s.SId,

s.Sname,

b.avg_score

FROM

Student s

INNER JOIN (

SELECT

SId,

avg(Score) AS avg_score

FROM

SC

WHERE

Score < 60

GROUP BY

SId

HAVING

count(*) >= 2

) b ON s.SId = b.SId;

-- 12.检索" 01 "课程分数小于 60,按分数降序排列的学生信息

SELECT

s.* from Student s

INNER JOIN (

SELECT

*

FROM

SC

WHERE

CId = '01' and Score < 60

) b ON s.SId = b.SId

ORDER BY

b.Score DESC;

-- 13. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

SELECT

s.*, b.avg_score

FROM

SC s

INNER JOIN (

SELECT

SId,

avg(Score) AS avg_score

FROM

SC

GROUP BY

SId

) b ON s.SId = b.SId

ORDER BY

b.avg_score DESC;

/* 14.查询各科成绩最高分、最低分和平均分:以如下形式显示:

课程 ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率

及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90

要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列*/

-- case when 的应用

SELECT a.Cname, b.* from Course a inner join

(SELECT

CId,

MAX(Score) as 最高分,

MIN(Score) as 最低分,

avg(Score) as 平均分,

COUNT(*) as 选修人数,

sum(case when Score >=60 then 1 else 0 END)/COUNT(*) as 及格率,

SUM(case when Score>=70 and Score<80 then 1 else 0 end)/COUNT(*) as 中等率,

SUM(case when Score>=80 and Score<90 then 1 else 0 end)/COUNT(*) as 优良率,

SUM(case when Score>=90 then 1 else 0 end)/COUNT(*) as 优秀率

from SC

GROUP BY CId order by count(*) desc, CId ASC) b on a.CId=b.CId;

-- 15. 按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺 (赋值变量的用法)

-- 15.1 按各科成绩进行排序,并显示排名, Score 重复时合并名次

-- 16.  查询学生的总成绩,并进行排名,总分重复时保留名次空缺

-- 16.1 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺

-- 17. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比

SELECT

CId,

concat(SUM(case when Score>=0 and Score <=60 then 1 else 0 end)/ COUNT(*)*100,'%') as '[0,60]',

concat(SUM(case when Score>=60 and Score <=70 then 1 else 0 end)/ COUNT(*)*100,'%') as '[60,70]',

concat(SUM(case when Score>=70 and Score <=85 then 1 else 0 end)/ COUNT(*)*100,'%') as '[70,85]',

concat(SUM(case when Score>=85 and Score <=100 then 1 else 0 end)/ COUNT(*)*100,'%') as '[85,100]'

from SC group by CId;

-- 18. 查询各科成绩前三名的记录(赋值变量的用法)

-- 19. 查询每门课程被选修的学生数

Select

CId, count(*) as cons

From

SC group by CId;

-- 20. 查询出只选修两门课程的学生学号和姓名

Select a.SId, a.Sname

From Student a Inner join

(Select

SId

From SC group by SId having count(CId) =2) b on a.SId=b.SId;

-- 21. 查询男生、女生人数

Select

Ssex, count(*)

From Student group by Ssex;

-- 22. 查询名字中含有「风」字的学生信息

Select * from Student

Where Sname like '%风%';

-- 23. 查询同名同性学生名单,并统计同名人数

SELECT s.*, cons

from Student s inner join

(SELECT a.Sname, a.Ssex, COUNT(*) as cons

from

Student a inner join Student b on a.Sname = b.Sname and a.Ssex = b.Ssex and a.SId != b.SId

GROUP BY a.Sname, a.Ssex) c on s.Sname = c.Sname and s.Ssex = c.Ssex;

-- 24. 查询 1990 年出生的学生名单

select *

From Student where year(Sage)=1990;

-- 25. 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列

Select

CId, avg(Score) as avg_score

From SC group by CId order by avg_score desc, CId asc;

-- 26. 查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩

Select

a.SId, a.Sname, b.avg_score

from Student a inner join

(Select

SId, avg(Score) as avg_score

From SC group by SId having avg_score>=85) b on a.Sid=b.Sid;

-- 27. 查询课程名称为「数学」,且分数低于 60 的学生姓名和分数

Select

Student.Sname, c.Score from Student inner join

(Select

a.SId, a.Score

From SC a inner join Course b on a.CId=b.CId and b.Cname='数学' and a.Score<60) c on Student.SId=c.SId;

-- 28. 查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)

SELECT

*

FROM

Student

LEFT JOIN SC ON Student.SId = SC.SId;

-- 29. 查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数

SELECT

s.Sname, b.Cname, a.Score

FROM

Student s

left join SC a on s.SId = a.SId

left JOIN Course b on a.CId = b.CId

where a.Score>70;

-- 30. 查询存在不及格的课程

SELECT DISTINCT CId from SC

where Score < 60;

-- 31. 查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名

Select a.SId, a.Sname, b.Score

From Student a

inner join SC b on a.SId = b.SId and b.CId='01' and b.Score>=80;

-- 32. 求每门课程的学生人数

SELECT CId, COUNT(*)

FROM SC

GROUP BY CId;

-- 33. 成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩

Select

a.*, b.Score

From Student a

inner join SC b on a.Sid=b.SId

Inner join Course c on b.CId=c.CId

Inner join Teacher d on d.TId=c.TId and d.Tname='张三' order by b.Score desc limit 1;

-- 34. 成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩 (赋值变量的用法)

-- 35. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

SELECT

DISTINCT a.*

from SC a inner join SC b on a.SId = b.SId

where a.CId != b.CId and a.Score = b.score;

SELECT *

from SC t1

where EXISTS (select * from SC t2 where t1.SId=t2.SId and t1.CId!=t2.CId and t1.Score = t2.Score);

-- 36. 查询每门功成绩最好的前两名 (赋值变量的用法)

-- 37. 统计每门课程的学生选修人数(超过 5 人的课程才统计)。

Select

CId, count(*) as cons

From SC

Group by CId having cons>5;

-- 38. 检索至少选修两门课程的学生学号

Select

SId

From SC

Group by SId having count(CId)>=2;

-- 39. 查询选修了全部课程的学生信息

Select * from Student

Where Sid in

( select

SId

from SC group by SId having count(CId)=(select count(*) from Course));

/* 需引入时间函数等

40. 查询各学生的年龄,只按年份来算

41. 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一

42. 查询本周过生日的学生

43. 查询下周过生日的学生

44. 查询本月过生日的学生

45. 查询下月过生日的学生 */

你可能感兴趣的:(2020-09-20 MySql经典45题)