表结构
1、学生表(学生编号,学生姓名,学生生日,学生性别)
student(sno, sname, birth, gender)
2、课程表(课程编号,课程名称,教师编号)
course(cno, cname, tno)
3、教师表(教师编号,教师姓名)
teacher(tno, tname)
4、成绩表(学生编号,课程编号,分数)
sc(sno, cno, score)
创建测试数据
-- 创建学生表
DROP TABLE IF EXISTS student;
CREATE TABLE IF NOT EXISTS student(
sno INT(11) NOT NULL AUTO_INCREMENT,
sname VARCHAR(20) NOT NULL,
birth DATE DEFAULT NULL,
gender ENUM('男', '女', '保密') DEFAULT '保密',
PRIMARY KEY(sno)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
-- 插入数据
INSERT INTO student VALUES(1, '赵雷', '1990-01-01', '男');
INSERT INTO student VALUES(2, '钱电', '1990-12-21', '男');
INSERT INTO student VALUES(3, '孙风', '1990-05-20', '男');
INSERT INTO student VALUES(4, '李云', '1990-08-06', '男');
INSERT INTO student VALUES(5, '周梅', '1991-12-01', '女');
INSERT INTO student VALUES(6, '吴兰', '1992-03-01', '女');
INSERT INTO student VALUES(7, '郑竹', '1989-07-01', '女');
INSERT INTO student VALUES(8, '王菊', '1990-01-20', '女');
-- 创建教师表
DROP TABLE IF EXISTS teacher;
CREATE TABLE IF NOT EXISTS teacher(
tno INT(11) NOT NULL AUTO_INCREMENT,
tname VARCHAR(20) NOT NULL,
PRIMARY KEY(tno)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
-- 插入数据
INSERT INTO teacher VALUES(1, '张三');
INSERT INTO teacher VALUES(2, '李四');
INSERT INTO teacher VALUES(3, '王五');
-- 创建课程表
DROP TABLE IF EXISTS course;
CREATE TABLE IF NOT EXISTS course(
cno INT(11) NOT NULL AUTO_INCREMENT,
cname VARCHAR(20) NOT NULL,
tno INT(11),
PRIMARY KEY(cno),
FOREIGN KEY(tno) REFERENCES teacher(tno)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
-- 插入数据
INSERT INTO course VALUES(1, '语文', 2);
INSERT INTO course VALUES(2, '数学', 1);
INSERT INTO course VALUES(3, '英语', 3);
-- 创建成绩表
DROP TABLE IF EXISTS sc;
CREATE TABLE IF NOT EXISTS sc(
sno INT(11) NOT NULL AUTO_INCREMENT,
cno INT(11) NOT NULL,
score INT(11),
FOREIGN KEY(sno) REFERENCES student(sno),
FOREIGN KEY(cno) REFERENCES course(cno)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
-- 插入数据
insert into sc values(1, 1, 80);
insert into sc values(1, 2, 90);
insert into sc values(1, 3, 99);
insert into sc values(2, 1, 70);
insert into sc values(2, 2, 60);
insert into sc values(2, 3, 80);
insert into sc values(3, 1, 80);
insert into sc values(3, 2, 80);
insert into sc values(3, 3, 80);
insert into sc values(4, 1, 50);
insert into sc values(4, 2, 30);
insert into sc values(4, 3, 20);
insert into sc values(5, 1, 76);
insert into sc values(5, 2, 87);
insert into sc values(6, 1, 31);
insert into sc values(6, 3, 34);
insert into sc values(7, 2, 89);
insert into sc values(7, 3, 98);
-- 查看表中数据
SELECT * FROM student;
SELECT * FROM teacher;
SELECT * FROM course;
SELECT * FROM sc;
1、查询"1"课程比"2"课程成绩高的学生的信息及课程分数
-- 方法一:
SELECT stu.*, s1.cno, s1.score, s2.cno, s2.score
FROM student stu
JOIN sc s1 ON stu.sno = s1.sno
JOIN sc s2 ON stu.sno = s2.sno
WHERE s1.cno = 1 AND s2.cno = 2 AND s1.score > s2.score;
-- 方法二:使用子查询
-- 先找到这两门课程的成绩
select sno, cno, score from sc where cno = 1;
SELECT sno, cno, score FROM sc WHERE cno = 2;
-- 下一步使用join把这两个查询结果连接起来
select stu.*, t1.cno, t1.score1, t2.cno, t2.score2
from student stu
join (
select sno, cno, score as score1
from sc
where cno = 1
) t1
on stu.sno = t1.sno
join (
select sno, cno, score as score2
from sc
where cno = 2
) t2
on stu.sno = t2.sno
where t1.score1 > t2.score2;
2、查询"1"课程比"2"课程成绩低的学生的信息及课程分数
-- 方法一:连接三张表
SELECT stu.*, s1.cno, s1.score, s2.cno, s2.score
FROM student stu
JOIN sc s1 ON stu.sno = s1.sno AND s1.cno = 1
JOIN sc s2 ON stu.sno = s2.sno AND s2.cno = 2
WHERE s1.score < s2.score;
3、查询平均成绩大于等于60分的学生的学生编号和学生姓名和平均成绩
-- 先查询平均成绩大于60的学生编号和平均成绩
SELECT sno, AVG(score) AS avgScore
FROM sc
GROUP BY sno
HAVING avgScore >= 60;
-- 然后和student表连接
SELECT stu.sno, stu.sname, t.avgScore
FROM student stu
JOIN (
SELECT sno, AVG(score) AS avgScore
FROM sc
GROUP BY sno
HAVING avgScore >= 60
) t
ON stu.sno = t.sno;
-- 方法二:
SELECT stu.sno, stu.sname, t.avgScore
FROM (
SELECT sno, AVG(score) AS avgScore
FROM sc
GROUP BY sno
HAVING AVG(score) >= 60
) t
LEFT JOIN student stu ON t.sno = stu.sno;
-- 方法三:
SELECT stu.sno, stu.sname, AVG(s.score) AS avgScore
FROM student stu
JOIN sc s ON stu.sno = s.sno
GROUP BY s.sno
HAVING AVG(s.score) >= 60;
4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩
SELECT stu.sno, stu.sname, AVG(s.score) AS avgScore
FROM student stu
JOIN sc s ON stu.sno = s.sno
GROUP BY s.sno
HAVING AVG(s.score) < 60;
5、查询所有学生的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 NULL )
-- 方法一:使用join连接两张表,然后按学生学号分组
SELECT stu.sno, stu.sname, COUNT(s.cno) sumCourse, SUM(s.score) sumScore
FROM student stu
LEFT JOIN sc s ON stu.sno = s.sno
GROUP BY stu.sno;
-- 方法二:
-- 使用子查询查出每个学生的选课总数和所有课程的总成绩
-- 然后再和student表连接
SELECT stu.sno, stu.sname, t.sumCourse, t.sumScore
FROM student stu
LEFT JOIN (
SELECT sno, COUNT(cno) AS sumCourse, SUM(score) AS sumScore
FROM sc
GROUP BY sno
) t
ON stu.sno = t.sno;
6、查询「李」姓老师的数量
SELECT COUNT(*)
FROM teacher
WHERE tname LIKE "李%";
7、查询学过「张三」老师授课的同学的信息
-- 方法一:使用子查询
-- 先查询 张三 老师的教师编号
SELECT tno
FROM teacher
WHERE teacher.tname = '张三';
-- 查询 张三 老师所教授的课程编号
SELECT cno
FROM course
WHERE course.tno = (
SELECT tno
FROM teacher
WHERE teacher.tname = '张三'
);
-- 完整查询语句
SELECT stu.*
FROM student stu
JOIN sc s ON stu.sno = s.sno
WHERE s.cno IN (
SELECT cno
FROM course
WHERE course.tno = (
SELECT tno
FROM teacher
WHERE teacher.tname = '张三'
)
);
-- 方法二:使用多重join连接
SELECT stu.*
FROM student stu
JOIN sc s ON stu.sno = s.sno
JOIN course c ON s.cno = c.cno
JOIN teacher t ON c.tno = t.tno
WHERE t.tname = '张三';
8、查询没学过"张三"老师授课的同学的信息
-- 思路:先查询学过张三老师授课的同学的学号,然后查询除了这些学号的同学
SELECT *
FROM student stu
WHERE sno NOT IN (
SELECT stu.sno
FROM student stu
JOIN sc s ON stu.sno = s.sno
JOIN course c ON s.cno = c.cno
JOIN teacher t ON c.tno = t.tno
WHERE t.tname = '张三'
);
9、查询学过编号为"1"并且也学过编号为"2"的课程的同学的信息
-- 方法一:
SELECT stu.*, s1.cno, s1.score, s2.cno, s2.score
FROM student stu
JOIN sc s1 ON stu.sno = s1.sno
JOIN sc s2 ON s1.sno = s2.sno
WHERE s1.cno = 1 AND s2.cno = 2;
-- 方法二:
SELECT stu.*, t1.cno, t1.score, t2.cno, t2.score
FROM student stu
JOIN (
SELECT *
FROM sc WHERE cno = 1
) t1
ON stu.sno = t1.sno
JOIN (
SELECT *
FROM sc WHERE cno = 2
) t2
ON t1.sno = t2.sno;
-- 方法三:
SELECT *
FROM student stu
WHERE stu.sno IN (
SELECT sno
FROM sc
WHERE cno = 1
) AND stu.sno IN (
SELECT sno
FROM sc
WHERE cno = 2
);
10、查询学过编号为"1"但是没有学过编号为"2"的课程的同学的信息(不存在显示null)
-- 方法一:
SELECT *
FROM student stu
WHERE stu.sno IN (
SELECT sno
FROM sc
WHERE cno = 1
) AND stu.sno NOT IN (
SELECT sno
FROM sc
WHERE cno = 2
);
11、查询没有学全所有课程的同学的信息
-- 思路:反向思维,先查询学全所有课程的同学的学号
SELECT s.sno
FROM sc s
GROUP BY s.sno
HAVING COUNT(cno) = (
SELECT COUNT(*)
FROM course
);
-- 然后选择不再这些学号范围的同学
SELECT stu.*
FROM student stu
WHERE stu.sno NOT IN (
SELECT s.sno
FROM sc s
GROUP BY s.sno
HAVING COUNT(cno) = (
SELECT COUNT(*)
FROM course
)
);
-- 方法二:
-- 先查询所有课程的总数
SELECT COUNT(*)
FROM course;
-- 查询所学课程数量小于课程总数的学生信息
SELECT stu.*
FROM student stu
LEFT JOIN sc s ON stu.sno = s.sno
GROUP BY stu.sno
HAVING COUNT(cno) < (
SELECT COUNT(cno)
FROM course
);
12、查询至少有一门课与学号为"1"的学生所学相同的学生的信息
-- 先查询学生编号为1的学生所学的课程编号
SELECT cno
FROM sc
WHERE sno = 1;
-- 再查询学了以上结果集中的课程的学生信息并排除sno=1的同学
SELECT DISTINCT stu.*
FROM student stu
JOIN sc s ON stu.sno = s.sno AND stu.sno <> 1
WHERE s.cno IN (
SELECT cno
FROM sc
WHERE sno = 1
);
-- 方法二:
SELECT stu.*
FROM student stu
WHERE stu.sno IN (
SELECT DISTINCT s1.sno
FROM sc s1
WHERE s1.cno IN (
SELECT s2.cno
FROM sc s2
WHERE s2.sno = 1
)
)AND stu.sno <> 1;
13、查询和"1"号的学生学习的课程完全相同的其他学生的信息
-- 查询1号学生所学的课程
SELECT cno
FROM sc
WHERE sno = 1;
-- 查询1号学生所学的课程的总数
SELECT COUNT(*)
FROM sc
WHERE sno = 1;
-- 查询所学的课程以及课程总数符合上述结果集的学生
SELECT stu.*
FROM student stu
JOIN sc s ON stu.sno = s.sno
WHERE s.cno IN (
SELECT cno
FROM sc
WHERE sno = 1
)
AND stu.sno <> 1
GROUP BY stu.sno
HAVING COUNT(s.cno) = (
SELECT COUNT(*)
FROM sc
WHERE sno = 1
);
-- 方法二
SELECT stu.*
FROM student stu
WHERE stu.sno IN (
SELECT sno
FROM (
SELECT *
FROM sc s
WHERE s.cno IN (
SELECT cno
FROM sc
WHERE sno = 1
)
) t
GROUP BY t.sno
HAVING COUNT(cno) = (
SELECT COUNT(cno)
FROM sc s
WHERE sno = 1
)
)
AND stu.sno <> 1;
14、查询没学过"张三"老师讲授的任一门课程的学生姓名
-- 查询张三老师的教师编号
SELECT tno
FROM teacher
WHERE tname = '张三';
-- 查询张三老师教授的课程
SELECT cno
FROM course
WHERE tno = (
SELECT tno
FROM teacher
WHERE tname = '张三'
);
-- 查询学过李建民老师的课程的学生编号
SELECT sno
FROM sc
WHERE cno IN (
SELECT cno
FROM course
WHERE tno IN (
SELECT tno
FROM teacher
WHERE tname='张三'
)
);
-- 完整查询:
SELECT *
FROM student stu
WHERE stu.sno NOT IN (
SELECT sno
FROM sc
WHERE cno = (
SELECT cno
FROM course
WHERE tno = (
SELECT tno
FROM teacher
WHERE tname='张三'
)
)
);
-- 方法二:
SELECT *
FROM student stu
WHERE stu.sno NOT IN (
SELECT s.sno
FROM (
SELECT c.cno, c.cname
FROM teacher t, course c
WHERE t.tno = c.tno AND t.tname = "张三"
) t, sc s
WHERE t.cno = s.cno
);
-- 方法三:
SELECT *
FROM student stu
WHERE stu.sno NOT IN (
SELECT s.sno
FROM sc s
LEFT JOIN course c ON s.cno = c.cno
LEFT JOIN teacher t ON c.tno = t.tno
WHERE t.tname = "张三"
);
15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT stu.sno, stu.sname, AVG(s.score) AS avgScore
FROM student stu
JOIN sc s ON stu.sno = s.sno
WHERE s.score < 60
GROUP BY stu.sno
HAVING COUNT(s.cno) >= 2;
16、检索"1"课程分数小于60,按分数降序排列的学生信息
SELECT stu.*
FROM student stu
JOIN sc s ON stu.sno = s.sno
WHERE s.cno = 1 AND s.score < 60
ORDER BY s.score DESC;
17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
-- 1)要求显示所有学生,因此需要使用外联
-- 2)平均成绩:理解为每个学生的所有课程的平均成绩
-- 查询每个学生的平均成绩
SELECT stu.sno, AVG(s.score) AS avgScore
FROM student stu
LEFT JOIN sc s ON stu.sno = s.sno
GROUP BY stu.sno;
-- 查询所有学生的所有课程成绩并与上面的平均成绩表连接
SELECT stu.sno, stu.sname, s.cno, s.score, t.avgScore
FROM student stu
LEFT JOIN sc s ON stu.sno = s.sno
LEFT JOIN (
SELECT stu.sno, AVG(s.score) AS avgScore
FROM student stu
LEFT JOIN sc s ON stu.sno = s.sno
GROUP BY stu.sno
) t
ON s.sno = t.sno
ORDER BY t.avgScore DESC;
-- 方法二:
SELECT stu.*, t2.cno, t2.score, t2.avgScore
FROM student stu
JOIN (
SELECT s.sno, s.cno, s.score, t.avgScore
FROM sc s
LEFT JOIN (
SELECT s2.sno, AVG(s2.score) avgScore
FROM sc s2
GROUP BY s2.sno
) t
ON s.sno = t.sno
) t2
ON stu.sno = t2.sno
ORDER BY t2.avgScore DESC;
-- 方法三:
SELECT s.sno,
(SELECT score FROM sc WHERE sno = s.sno AND cno = 1) AS "语文",
(SELECT score FROM sc WHERE sno = s.sno AND cno = 2) AS "数学",
(SELECT score FROM sc WHERE sno = s.sno AND cno = 3) AS "英语",
AVG(s.score) AS avgScore
FROM sc s
GROUP BY s.sno
ORDER BY avgScore DESC;
18、查询各科成绩最高分、最低分和平均分:
-- 以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
-- 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
-- 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
-- 方法一:
SELECT c.cno, c.cname,
COUNT(s.cno) AS "选修人数",
MAX(s.score) AS "最高分",
MIN(s.score) AS "最低分",
AVG(s.score) AS "平均分",
SUM(CASE WHEN s.score >= 60 THEN 1 ELSE 0 END)/COUNT(1) AS "及格率",
SUM(CASE WHEN s.score BETWEEN 70 AND 80 THEN 1 ELSE 0 END)/COUNT(1) AS "中等率",
SUM(CASE WHEN s.score BETWEEN 80 AND 90 THEN 1 ELSE 0 END)/COUNT(1) AS "优良率",
SUM(CASE WHEN s.score >= 90 THEN 1 ELSE 0 END)/COUNT(1) AS "优秀率"
FROM course c
JOIN sc s ON c.cno = s.cno
GROUP BY c.cno, c.cname
ORDER BY COUNT(s.cno) DESC, c.cno;
-- 方法二:
SELECT c.cno, c.cname,
(SELECT MAX(score) FROM sc WHERE cno = c.cno) AS "最高分",
(SELECT MIN(score) FROM sc WHERE cno = c.cno) AS "最低分",
(SELECT CAST(AVG(score) AS DECIMAL(18,2)) FROM sc WHERE cno = c.cno) AS "平均分",
(SELECT COUNT(1) FROM sc WHERE cno = c.cno AND score >= 60)/(SELECT COUNT(1) FROM sc WHERE cno = c.cno) "及格率",
(SELECT COUNT(1) FROM sc WHERE cno = c.cno AND score BETWEEN 70 AND 80)/(SELECT COUNT(1) FROM sc WHERE cno = c.cno) "中等率",
(SELECT COUNT(1) FROM sc WHERE cno = c.cno AND score BETWEEN 80 AND 90)/(SELECT COUNT(1) FROM sc WHERE cno = c.cno) "优良率",
(SELECT COUNT(1) FROM sc WHERE cno = c.cno AND score >= 90)/(SELECT COUNT(1) FROM sc WHERE cno = c.cno) "优秀率"
FROM course c;
-- 方法三:
SELECT t.cno,
COUNT(t.sno),
MAX(t.score),
MIN(t.score),
AVG(t.score),
SUM(及格)/COUNT(t.sno) AS 及格率,
SUM(中等)/COUNT(t.sno) AS 中等率,
SUM(优良)/COUNT(t.sno) AS 优良率,
SUM(优秀)/COUNT(t.sno) AS 优秀率
FROM (
SELECT *,
CASE WHEN score >= 60 THEN 1 ELSE 0 END AS "及格",
CASE WHEN score BETWEEN 70 AND 80 THEN 1 ELSE 0 END AS "中等",
CASE WHEN score BETWEEN 80 AND 90 THEN 1 ELSE 0 END AS "优良",
CASE WHEN score >= 90 THEN 1 ELSE 0 END AS "优秀"
FROM sc
) t
GROUP BY t.cno
ORDER BY COUNT(t.sno) DESC, t.cno;
19、按各科成绩进行排序,并显示排名
SELECT s.*,
(SELECT COUNT(1) FROM sc WHERE cno = s.cno AND score > s.score) + 1 AS px
FROM sc s
ORDER BY s.score;
20、查询学生的总成绩并进行排名
SELECT t.*, @rank:=@rank + 1 AS rank
FROM (
SELECT s.sno, SUM(score)
FROM sc s
GROUP BY s.sno
ORDER BY SUM(score) DESC
) t, (SELECT @rank:=0) r;
21、查询不同老师所教不同课程平均分从高到低显示
SELECT t.tno, t.tname, c.cname, AVG(s.score)
FROM sc s, course c, teacher t
WHERE s.cno = c.cno AND c.tno = t.tno
GROUP BY s.cno
ORDER BY AVG(s.score) DESC;
22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
-- 先查询每个课程的成绩第2名到第3名的学生信息及该课程成绩
-- 然后使用union 联合
SELECT st.*, t.cno, t.score
FROM student st
JOIN (
SELECT *
FROM sc s WHERE s.cno = 1
ORDER BY s.score DESC
LIMIT 1,2
) t
ON st.sno = t.sno
UNION
SELECT st.*, t.cno, t.score
FROM student st
JOIN (
SELECT *
FROM sc s WHERE s.cno = 2
ORDER BY s.score DESC
LIMIT 1,2
) t
ON st.sno = t.sno
UNION
SELECT st.*, t.cno, t.score
FROM student st
JOIN (
SELECT *
FROM sc s WHERE s.cno = 3
ORDER BY s.score DESC
LIMIT 1,2
) t
ON st.sno = t.sno;
23、统计各科成绩各分数段人数:
-- 课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比
SELECT s.cno, c.cname,
SUM(CASE WHEN score BETWEEN 85 AND 100 THEN 1 ELSE 0 END) AS '[100-85]',
SUM(CASE WHEN score BETWEEN 85 AND 100 THEN 1 ELSE 0 END)/COUNT(s.sno) AS '[100-85]百分比',
SUM(CASE WHEN score BETWEEN 70 AND 85 THEN 1 ELSE 0 END) AS '[85-70]',
SUM(CASE WHEN score BETWEEN 70 AND 85 THEN 1 ELSE 0 END)/COUNT(s.sno) AS '[85-70]百分比',
SUM(CASE WHEN score BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS '[70-60]',
SUM(CASE WHEN score BETWEEN 60 AND 70 THEN 1 ELSE 0 END)/COUNT(s.sno) AS '[70-60]百分比',
SUM(CASE WHEN score BETWEEN 0 AND 60 THEN 1 ELSE 0 END) AS '[60-0]',
SUM(CASE WHEN score BETWEEN 0 AND 60 THEN 1 ELSE 0 END)/COUNT(s.sno) AS '[60-0]百分比'
FROM course c
JOIN sc s ON c.cno = s.cno
GROUP BY s.cno, c.cname;
24、查询学生平均成绩及其名次
SELECT t.*, @rownum:=@rownum + 1 AS rowNum
FROM (
SELECT s.sno, AVG(s.score) AS avgScore
FROM sc s
GROUP BY s.sno
ORDER BY avgScore DESC
) t, (SELECT @rownum:=0) r;
25、查询各科成绩前三名的记录
-- 思路:
-- 1.选出s2表比s1表成绩大的所有组
-- 2.选出比当前id成绩大的 小于三个的
SELECT s1.sno, s1.cno, s1.score
FROM sc s1
LEFT JOIN sc s2 ON s1.cno = s2.cno AND s1.score < s2.score
GROUP BY s1.sno, s1.cno, s1.score
HAVING COUNT(s2.score) < 3
ORDER BY s1.cno, s1.score DESC;
26、查询每门课程被选修的学生数
-- 方法一:显示课程名称
SELECT c.cno, c.cname, COUNT(*) AS "被选修次数"
FROM course c
LEFT JOIN sc s ON c.cno = s.cno
GROUP BY c.cno;
-- 方法二:只显示课程号
SELECT cno, COUNT(sno) AS "被选修次数"
FROM sc
GROUP BY cno;
27、查询出只有两门课程的全部学生的学号和姓名
-- 方法一:
SELECT st.sno, st.sname
FROM student st
WHERE st.sno IN (
SELECT sno
FROM sc s
GROUP BY s.sno
HAVING COUNT(s.cno) = 2
);
-- 方法二:
SELECT stu.sno, stu.sname
FROM student stu
JOIN (
SELECT sno, COUNT(*) AS c_count
FROM sc
GROUP BY sno
) t
ON stu.sno = t.sno
WHERE t.c_count = 2;
28、查询男生、女生人数
-- 方法一:
SELECT gender, COUNT(*) AS "性别"
FROM student stu
GROUP BY gender;
-- 方法二:
SELECT st.gender, COUNT(*) FROM student st WHERE st.gender = "男"
UNION
SELECT st.gender, COUNT(*) FROM student st WHERE st.gender = "女";
29、查询名字中含有"风"字的学生信息
SELECT *
FROM student st
WHERE st.sname LIKE "%风%";
30、查询同名同姓学生名单,并统计同名人数
-- 方法一:
SELECT a.*, b.sameNum
FROM student a
LEFT JOIN (
SELECT sname, gender, COUNT(*) AS sameNum
FROM student
GROUP BY sname, gender
) b
ON a.sname = b.sname AND a.gender = b.gender
WHERE b.sameNum > 1;
-- 方法二:
SELECT st.sname, st.gender, COUNT(*) countNum
FROM student st
GROUP BY st.sname, st.gender
HAVING countNum >= 2;
31、查询1990年出生的学生名单(注:student表中birth列的类型是datetime)
-- 方法一:
SELECT *
FROM student st
WHERE YEAR(birth) = 1990;
-- 方法二:
SELECT *
FROM student st
WHERE birth LIKE "1990%";
32、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
SELECT cno, AVG(score) AS avgScore
FROM sc
GROUP BY cno
ORDER BY avgScore DESC, cno;
33、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
-- 方法一:使用分组
SELECT stu.sno, stu.sname, AVG(score) avgScore
FROM student stu
JOIN sc s ON stu.sno = s.sno
GROUP BY stu.sno
HAVING avgScore > 85;
-- 方法二:使用子查询
SELECT stu.sno, stu.sname, t.avgScore
FROM student stu
LEFT JOIN (
SELECT sno, AVG(score) AS avgScore
FROM sc
GROUP BY sno
) t
ON stu.sno = t.sno
WHERE t.avgScore > 85;
34、查询课程名称为"数学",且分数低于60的学生姓名和分数
-- 方法一:
SELECT stu.sname, s.score
FROM student stu
JOIN sc s ON stu.sno = s.sno
WHERE s.cno = (
SELECT cno
FROM course
WHERE cname = "数学"
) AND s.score < 60;
-- 方法二:
SELECT stu.sname, t.score
FROM (
SELECT *
FROM sc
WHERE cno = (
SELECT cno
FROM course
WHERE cname = "数学"
) AND score < 60
) t
LEFT JOIN student stu ON t.sno = stu.sno;
35、查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
-- 方法一:显示课程名称
SELECT stu.*, c.cno, c.cname, s.score
FROM student stu
LEFT JOIN sc s ON stu.sno = s.sno
LEFT JOIN course c ON s.cno = c.cno
ORDER BY stu.sno;
-- 方法二:只显示课程编号
SELECT stu.*, s.cno, s.score
FROM student stu
LEFT JOIN sc s ON stu.sno = s.sno;
36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数
-- 方法一:
SELECT stu.sname, c.cname, s.score
FROM student stu
JOIN sc s ON stu.sno = s.sno
JOIN course c ON s.cno = c.cno
WHERE s.score > 70
ORDER BY stu.sno, c.cname;
-- 方法二:
SELECT stu.sname, d.cname, d.score
FROM (
SELECT b.*, c.cname
FROM (
SELECT *
FROM sc
WHERE score > 70
) b
LEFT JOIN course c ON b.cno = c.cno
) d
LEFT JOIN student stu ON d.sno = stu.sno
ORDER BY stu.sno, d.cname;
-- 方法三:
SELECT st.sname, c.cname, s.score
FROM student st, course c, sc s
WHERE st.sno = s.sno AND c.cno = s.cno AND s.score > 70;
37、查询不及格的课程
SELECT DISTINCT c.cname
FROM course c
JOIN sc s ON c.cno = s.cno
WHERE s.score < 60;
38、查询课程编号为1且课程成绩在80分以上的学生的学号和姓名
-- 方法一:先连接再过滤
SELECT stu.sno, stu.sname
FROM student stu
JOIN sc s ON stu.sno = s.sno
WHERE s.cno = 1 AND s.score >= 80;
-- 方法二:先过滤再连接
SELECT stu.sno, stu.sname
FROM (
SELECT *
FROM sc
WHERE score >= 80 AND cno = 1
) t
LEFT JOIN student stu ON t.sno = stu.sno;
-- 方法三:
SELECT st.sno, st.sname
FROM student st, course c, sc s
WHERE st.sno = s.sno AND c.cno = s.cno AND c.cno = 1 AND s.score >= 80;
39、求每门课程的学生人数
SELECT cno, COUNT(*)
FROM sc
GROUP BY cno;
40、查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩
-- 方法一:
SELECT st.*, s.score
FROM student st
JOIN sc s ON st.sno = s.sno
WHERE s.cno = (
SELECT cno
FROM course c
WHERE c.tno = (
SELECT tno
FROM teacher t
WHERE t.tname = "张三"
)
)
ORDER BY s.score DESC
LIMIT 1;
-- 方法二:
SELECT stu.*, s.score
FROM student stu, sc s, course c, teacher t
WHERE stu.sno = s.sno AND s.cno = c.cno AND c.tno = t.tno AND t.tname = "张三"
ORDER BY s.score DESC
LIMIT 1;
41、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
SELECT DISTINCT s1.*
FROM sc s1
JOIN sc s2 ON s1.sno = s2.sno
WHERE s1.score = s2.score AND s1.cno <> s2.cno;
42、查询每门功成绩最好的前两名
-- 方法一:
SELECT s1.*
FROM sc s1
WHERE (
SELECT COUNT(1)
FROM sc s2
WHERE s1.cno = s2.cno AND s1.score <= s2.score
) <= 2
ORDER BY s1.cno;
-- 方法二:
SELECT a.sno, a.cno
FROM sc AS a
LEFT JOIN sc b ON a.cno = b.cno AND a.score < b.score
GROUP BY a.sno, a.cno
HAVING COUNT(b.cno) < 2
ORDER BY a.cno;
43、统计每门课程的学生选修人数(超过5人的课程才统计)。
-- 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
SELECT s.cno, COUNT(*) AS c_count
FROM sc s
GROUP BY s.cno
HAVING c_count > 5
ORDER BY c_count DESC, s.cno;
44、检索至少选修两门课程的学生学号
SELECT sno
FROM sc
GROUP BY sno
HAVING COUNT(cno) >= 2;
45、查询选修了全部课程的学生信息
-- 方法一:
SELECT st.*
FROM student st, sc s
WHERE st.sno = s.sno
GROUP BY s.sno
HAVING COUNT(*) = (
SELECT DISTINCT COUNT(*)
FROM course
);
-- 方法二:
SELECT stu.*
FROM student stu
LEFT JOIN sc s ON stu.sno = s.sno
GROUP BY stu.sno
HAVING COUNT(cno) = (
SELECT DISTINCT COUNT(*)
FROM course
);
46、查询各学生的年龄
-- 只按年份来算
SELECT
sno, sname,
YEAR(NOW()) - YEAR(birth) AS "年龄"
FROM student;
-- 按照出生日期来算,当前月日 < 出生年月的月日则年龄减一
-- 获取当前月日
SELECT DATE_FORMAT(CURRENT_DATE, '%m-%d');
-- 完整语句
SELECT
stu.sno,
stu.sname,
stu.birth,
YEAR(NOW()) - YEAR(birth) AS "按年计算的年龄",
CASE
WHEN DATE_FORMAT(CURRENT_DATE, '%m-%d') < DATE_FORMAT(birth, '%m-%d')
THEN YEAR(NOW()) - YEAR(birth) - 1
ELSE YEAR(NOW()) - YEAR(birth)
END AS "按日期计算的年龄"
FROM student stu;
47、查询本周过生日的学生
-- 获取第几周
SELECT WEEK(CURRENT_DATE);
-- 查询是否本周过生日
SELECT
stu.sname,
stu.birth,
WEEK(birth) AS "出生在第几周",
WEEK(CURRENT_DATE, 1) AS "当前周",
WEEK(birth) = WEEK(CURRENT_DATE, 1) AS "是否本周过生日"
FROM student stu;
-- 方法一:
SELECT st.*
FROM student st
WHERE WEEK(birth) = WEEK(NOW(), 1);
48、查询下周过生日的学生
SELECT st.*
FROM student st
WHERE WEEK(birth) = WEEK(NOW(), 1) + 1;
49、查询本月过生日的学生
SELECT st.*
FROM student st
WHERE MONTH(birth) = MONTH(NOW());
50、查询下月过生日的学生
SELECT st.*
FROM student st
WHERE MONTH(birth) = MONTH(NOW()) + 1;
更新日期:2020年5月23日