-- 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. 查询下月过生日的学生 */