经典SQL50练习题MySQL版

本文提供了50道关于MySQL的SQL练习题,涵盖了表结构介绍、数据导入及各种SQL查询操作,适合进阶学习者巩固提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.表结构详情

--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 分数

2.建表与数据导入

create table Student(SID varchar(10),Sname nvarchar(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 nvarchar(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 nvarchar(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);

3.SQL


-- 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数
-- 01课程,02课程同时存在
	-- 查询学生的01课程,02课程(三张表:学生表,01课程表,02课程表)
SELECT * FROM student s,sc sc1,sc sc2 
WHERE s.sid=sc1.sid AND s.sid=sc2.sid 
AND sc1.cid=01 AND sc2.cid=02
-- 查询"01"课程比"02"课程成绩高的学生的信息及课程分数
SELECT * FROM student s,sc sc1,sc sc2 
WHERE s.sid=sc1.sid AND s.sid=sc2.sid 
AND sc1.cid=01 AND sc2.cid=02		
AND sc1.score>sc2.score

-- reference
SELECT s.*,sc1.score ,sc2.score  
FROM student s,sc sc1,sc sc2 
WHERE s.sid=sc1.sid AND s.sid=sc2.sid 
AND sc1.cid='01' AND sc2.cid='02'	
AND sc1.score>sc2.score

-- 01课程,02课程不同时存在

SELECT * FROM student s 
LEFT JOIN sc sc1 ON s.sid=sc1.sid AND sc1.cid='01'
LEFT JOIN sc sc2 ON s.sid=sc2.sid AND sc2.cid='02'
WHERE IFNULL(sc1.score,0) > IFNULL(sc2.score,0)


-- 2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数
-- 3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
-- 学生都存在成绩
	-- 查询学生和成绩
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid

	-- 查询学生和成绩平均成绩
SELECT s.sid,s.sname,AVG(sc.score) FROM student s,sc sc 
WHERE s.sid=sc.sid GROUP BY s.sid

	-- 平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
SELECT s.sid,s.sname,AVG(sc.score) FROM student s,sc sc 
WHERE s.sid=sc.sid GROUP BY s.sid
HAVING AVG(sc.score)>=60
ORDER BY s.sid 

-- DECIMAL(5,2),则该字段可以存储-999.99~999.99,最大值为999.99。
-- 也就是说D表示的是小数部分长度,(M-D)表示的是整数部分长度
-- CAST(源数据)别名  功能-->起别名
-- reference
SELECT a.SID , a.Sname , CAST(AVG(b.score) AS DECIMAL(18,2)) avg_score
FROM Student a , sc b
WHERE a.SID = b.SID
GROUP BY a.SID , a.Sname
HAVING CAST(AVG(b.score) AS DECIMAL(18,2)) >= 60
ORDER BY a.SID

-- 学生不存在成绩
	-- 查询学生与成绩
SELECT * FROM student s LEFT JOIN sc sc ON s.sid=sc.sid

	-- 查询学生与平均成绩
SELECT *,AVG(sc.score) FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
GROUP BY s.sid

	-- 平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
SELECT s.sid,s.sname,IFNULL(AVG(sc.score),0) FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
GROUP BY s.sid
HAVING IFNULL(AVG(sc.score),0)>60
-- 4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩

-- 5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
-- 5.1、查询所有有成绩的SQL

	-- 查询学生与成绩表
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid

	-- 查询学生与成绩表 选课总数
SELECT *,COUNT(*) FROM student s,sc sc WHERE s.sid=sc.sid GROUP BY s.sid

	-- 查询学生与成绩表 选课总数 所有课程的总成绩
SELECT s.sid,s.sname,COUNT(sc.cid) 选课总数,SUM(sc.score)总成绩 
FROM student s,sc sc 
WHERE s.sid=sc.sid 
GROUP BY s.sid

-- reference
SELECT a.SID  学生编号 , a.Sname  学生姓名 , COUNT(b.CID) 选课总数, SUM(score)  所有课程的总成绩 
FROM Student a , SC b
WHERE a.SID = b.SID
GROUP BY a.SID,a.Sname
ORDER BY a.SID

-- 5.2、查询所有(包括有成绩和无成绩)的SQL
SELECT s.sid,s.sname,COUNT(sc.cid) 选课总数,SUM(IFNULL(sc.score,0))总成绩 
FROM student s LEFT JOIN sc sc 
ON s.sid=sc.sid 
GROUP BY s.sid

-- reference
SELECT a.SID  学生编号 , a.Sname  学生姓名 , COUNT(b.CID) 选课总数, SUM(score)  所有课程的总成绩 
FROM Student a LEFT JOIN SC b
ON a.SID = b.SID
GROUP BY a.SID,a.Sname
ORDER BY a.SID

-- 6、查询"李"姓老师的数量
-- 方法1
SELECT COUNT(*) FROM teacher t WHERE tname LIKE '李%'
SELECT COUNT(tname) FROM teacher t WHERE tname LIKE '李_'
-- 方法2
-- reference
SELECT COUNT(Tname) 李姓老师的数量 FROM Teacher WHERE LEFT(Tname,1) = '李'

-- 7、查询学过"张三"老师授课的同学的信息

-- 7、查询学过"张三"老师授课的同学的信息
	-- 老师授课
SELECT * FROM teacher t,course c WHERE t.tid=c.tid
        -- 张三老师授课
SELECT * FROM teacher t,course c WHERE t.tid=c.tid AND t.tname='张三'
        -- 学生与成绩表
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid

-- 学过"张三"老师授课的同学的信息
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid
AND sc.cid IN(SELECT c.cid FROM teacher t,course c 
WHERE t.tid=c.tid AND t.tname='张三')

-- 方式二(推荐)
-- 查询学过"张三"老师授课的同学的信息
-- 四张表 老师,课程,学生,成绩
-- 去除笛卡尔积
-- 课程表关联老师 c.tid=t.tid 
-- 成绩表关联学生 sc.sid=s.sid
-- 成绩表关联课程 sc.cid=c.cid

-- 查询老师授课的同学的信息
SELECT * FROM student s,sc sc,teacher t,course c
WHERE sc.sid=s.sid AND c.tid=t.tid AND sc.cid=c.cid

-- 查询学过"张三"老师授课的同学的信息
SELECT s.* FROM student s,sc sc,teacher t,course c
WHERE sc.sid=s.sid AND c.tid=t.tid AND sc.cid=c.cid
AND t.tname='张三'

-- reference
SELECT DISTINCT Student.* FROM Student , SC , Course , Teacher
WHERE Student.SID = SC.SID AND SC.CID = Course.CID AND Course.TID = Teacher.TID 
AND Teacher.Tname = '张三'
ORDER BY Student.SID

-- 8、查询没学过"张三"老师授课的同学的信息
	-- 查询学过"张三"老师授课的同学的信息
SELECT * FROM student s,sc sc,teacher t,course c
WHERE sc.sid=s.sid AND c.tid=t.tid AND sc.cid=c.cid
AND t.tname='张三'
-- 错误 方式一:
-- 这样只是在查询 李四,王五老师授课的信息 该生有没有被张三老师教过并没有查询
SELECT * FROM student s,sc sc,teacher t,course c
WHERE sc.sid=s.sid AND c.tid=t.tid AND sc.cid=c.cid
AND (t.tname='李四' OR t.tname='王五')

SELECT * FROM student s,sc sc,teacher t,course c
WHERE sc.sid=s.sid AND c.tid=t.tid AND sc.cid=c.cid
AND t.tname IN('李四','王五')

SELECT * FROM student s,sc sc,teacher t,course c
WHERE sc.sid=s.sid AND c.tid=t.tid AND sc.cid=c.cid
AND t.tname NOT IN('张三')

-- 方式二:
SELECT * FROM student s2 
WHERE s2.sid NOT IN(SELECT s.sid FROM student s,sc sc,teacher t,course c
WHERE sc.sid=s.sid AND c.tid=t.tid AND sc.cid=c.cid
AND t.tname='张三')

-- reference
SELECT m.* FROM Student m 
WHERE SID NOT IN (SELECT DISTINCT SC.SID FROM SC , Course , Teacher 
WHERE SC.CID = Course.CID AND Course.TID = Teacher.TID AND Teacher.Tname = '张三')
ORDER BY m.SID

-- 9、查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息
	-- 查询学生课程信息(两张表) 
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid
	-- 查询学过01,02课程的学生课程信息
	-- 这样查询的是学过01或02课程的信息
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid IN(01,02)
	-- 查询学过编号为"01"或编号为"02"的课程的同学的信息
SELECT * FROM student s 
WHERE s.sid IN(SELECT s.sid FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid IN(01,02))

-- 总结 思路很重要 不先想清楚 写了也白写
-- 思路 先找出学过01课程的学生 再学过01课程的学生中再找学过02课程的学生
-- 学过01课程的学生 
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid=01
-- 查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息
SELECT s.* FROM student s,sc sc 
WHERE s.sid=sc.sid AND sc.cid=02
AND s.sid IN(SELECT sc.sid FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid=01)

SELECT s.* FROM student s,sc sc 
WHERE s.sid=sc.sid AND sc.cid=02
AND EXISTS(SELECT 1 FROM sc sc2 WHERE sc2.sid=sc.sid AND sc2.cid=01)


SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid=01
SELECT *,9 FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid=01

-- 方法1
-- reference
SELECT Student.* FROM Student , SC 
WHERE Student.SID = SC.SID AND SC.CID = '01' 
AND EXISTS (SELECT 1 FROM SC SC_2 WHERE SC_2.SID = SC.SID AND SC_2.CID = '02') ORDER BY Student.SID
-- 方法2
-- reference
SELECT Student.* FROM Student , SC 
WHERE Student.SID = SC.SID AND SC.CID = '02' 
AND EXISTS (SELECT 1 FROM SC SC_2 WHERE SC_2.SID = SC.SID AND SC_2.CID = '01') ORDER BY Student.SID

-- 10、查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息
	-- 查询学过01课程的学生
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01' -- 123456
	-- 学过编号为"02"的课程的同学的信息
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='02' -- 123457
	-- 没有学过编号为"02"的课程的同学的信息
-- 错误:SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid not in (02)
SELECT * FROM student s WHERE sid 
NOT IN(SELECT s.sid FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid=02)
	-- 查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01'
AND s.sid IN(
SELECT s.sid FROM student s WHERE sid 
NOT IN(SELECT s.sid FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid=02))
-- 改进
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01'
AND s.sid NOT IN(
SELECT s.sid FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='02')
-- 再改进(新增成绩表2 用来记录02课程的信息 共用前面的学生表 
-- 这里的共用仅为表的引用 而非结果集 结果集相互独立 不受影响)
-- 用 AND等条件连接的子句 都是并列同时执行 如果有括弧 如in() 则每次先执行括弧里面的子句
-- 将结果作为整体条件 与前面的条件并列 
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01'
AND s.sid NOT IN(
SELECT s.sid FROM sc sc2 WHERE s.sid=sc2.sid AND sc2.cid='02')


SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='02' -- 123457
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01' -- 123456
-- 6
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01'
AND NOT EXISTS(
SELECT s.sid FROM sc sc2 WHERE s.sid=sc2.sid AND sc2.cid='02')
-- 12345
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01'
AND EXISTS(
SELECT s.sid FROM sc sc2 WHERE s.sid=sc2.sid AND sc2.cid='02')


-- reference
-- 方法1
SELECT Student.* FROM Student , SC WHERE Student.SID = SC.SID AND SC.CID = '01' 
AND NOT EXISTS (
SELECT 1 FROM SC SC_2 WHERE SC_2.SID = SC.SID AND SC_2.CID = '02') ORDER BY Student.SID
-- 这里 SELECT 后的变量可以任意更改 仅仅为了满足语法需求
-- 方法2
SELECT Student.* FROM Student , SC WHERE Student.SID = SC.SID AND SC.CID = '01' 
AND Student.SID NOT IN (
SELECT SC_2.SID FROM SC SC_2 WHERE SC_2.SID = SC.SID AND SC_2.CID = '02') ORDER BY Student.SID

-- 11、查询没有学全所有课程的同学的信息
-- 分析 分为两种情况 修了课程的学生和没修课程的学生 当然可以用外连接统一到一起查询
-- 1查询课程数量
SELECT COUNT(*) FROM course c
-- 2查询学生所修课程数量
SELECT *,COUNT(*) FROM student s,sc sc WHERE s.sid=sc.sid GROUP BY s.sid
-- 3查询所修课程数小于总课程数的学生
SELECT *,COUNT(*) FROM student s,sc sc WHERE s.sid=sc.sid GROUP BY s.sid
HAVING COUNT(*)<3

SELECT *,COUNT(*) 课程总数 FROM student s,sc sc WHERE s.sid=sc.sid GROUP BY s.sid
HAVING 课程总数<(SELECT COUNT(*) FROM course c)

SELECT *,COUNT(*) 课程总数 FROM student s,sc sc WHERE s.sid=sc.sid GROUP BY s.sid
HAVING 课程总数<ALL(SELECT COUNT(*) FROM course c)

-- 改进
SELECT * FROM student s LEFT JOIN sc sc ON s.sid=sc.sid GROUP BY s.sid
HAVING COUNT(*)<(SELECT COUNT(*)FROM course c)
-- reference
SELECT Student.* FROM Student LEFT JOIN SC ON Student.SID = SC.SID
GROUP BY Student.SID , Student.Sname , Student.Sage , Student.Ssex 
HAVING COUNT(CID) < (SELECT COUNT(CID) FROM Course)

-- 12、查询至少有一门课与学号为"01"的同学所学相同的同学的信息
-- 所有学生的课程信息
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid
-- "01"的同学所学的课程
SELECT *,sc.cid FROM student s,sc sc WHERE s.sid=sc.sid AND s.sid='01'

SELECT s.* FROM student s,sc sc WHERE s.sid=sc.sid
AND sc.cid IN(SELECT sc.cid FROM student s,sc sc WHERE s.sid=sc.sid AND s.sid='01')
GROUP BY s.sid
-- 改进
SELECT  DISTINCT s.* FROM student s,sc sc WHERE s.sid=sc.sid
AND sc.cid IN(SELECT sc.cid FROM student s,sc sc WHERE s.sid=sc.sid AND s.sid='01')
-- 再改进
SELECT  DISTINCT s.* FROM student s,sc sc WHERE s.sid=sc.sid
AND sc.cid IN(SELECT sc2.cid FROM sc sc2 WHERE sc2.sid='01')
-- ref
SELECT DISTINCT Student.* FROM Student , SC WHERE Student.SID = SC.SID 
AND SC.CID IN (SELECT CID FROM SC WHERE SID = '01') AND Student.SID <> '01'

-- 13、查询和"01"号的同学学习的课程完全相同的其他同学的信息
	-- 查询其它同学的课程信息
SELECT * FROM student s,sc sc WHERE s.sid <> '01' AND s.sid=sc.sid
	-- 统计其它同学的课程的数
SELECT s.*,COUNT(*)FROM student s,sc sc WHERE s.sid <> '01' AND s.sid=sc.sid GROUP BY sc.sid
	-- 统计01学生所学课程数
SELECT COUNT(*) FROM sc WHERE sc.sid='01' 
	-- 查询和"01"号的同学学习的课程完全相同的其他同学的信息
SELECT s.* FROM student s,sc sc WHERE s.sid <> '01' AND s.sid=sc.sid GROUP BY sc.sid
HAVING COUNT(*)=(SELECT COUNT(*) FROM sc WHERE sc.sid='01')
-- 以上写法有问题 这样统计的只是学科数目上与01学生相同而不区分科目 所以并不是完全相同
-- 当用06同学测试时错误就很明显了
SELECT s.* FROM student s,sc sc WHERE s.sid <> '06' AND s.sid=sc.sid GROUP BY sc.sid
HAVING COUNT(*)=(SELECT COUNT(*) FROM sc WHERE sc.sid='06')
-- 改进
-- 分析完全相同 即数量相同并且课程也相同
-- 01学生所学课程
SELECT sc.cid FROM sc sc WHERE sc.sid='01'
-- 统计01学生所学课程数
SELECT COUNT(*) FROM sc WHERE sc.sid='01' 
-- 1统计包含01学生课程的其他学生课程
SELECT * FROM sc WHERE sc.sid<>'01' AND sc.cid IN(SELECT sc.cid FROM sc sc WHERE sc.sid='01')
-- 2统计包含01学生课程的其他学生课程数量
SELECT *,COUNT(*) FROM sc WHERE sc.sid<>'01' AND sc.cid IN(SELECT sc.cid FROM sc sc WHERE sc.sid='01')
GROUP BY sc.sid
-- 3统计课程,课程数量与01学生相同的其他学生课程信息
SELECT *,COUNT(*) FROM sc WHERE sc.sid<>'01' AND sc.cid IN(SELECT sc.cid FROM sc sc WHERE sc.sid='01')
GROUP BY sc.sid HAVING COUNT(*)=(SELECT COUNT(*) FROM sc WHERE sc.sid='01')
-- 4统计课程,课程数量与01学生相同的其他学生id
SELECT sc.sid FROM sc WHERE sc.sid<>'01' AND sc.cid IN(SELECT sc.cid FROM sc sc WHERE sc.sid='01')
GROUP BY sc.sid HAVING COUNT(*)=(SELECT COUNT(*) FROM sc WHERE sc.sid='01')
-- 5查询和"01"号的同学学习的课程完全相同的其他同学的信息
SELECT * FROM student s WHERE s.sid IN(SELECT sc.sid FROM sc WHERE sc.sid<>'01' AND sc.cid IN(SELECT sc.cid FROM sc sc WHERE sc.sid='01')
GROUP BY sc.sid HAVING COUNT(*)=(SELECT COUNT(*) FROM sc WHERE sc.sid='01'))

SELECT * FROM student s WHERE 
s.sid IN(SELECT sc.sid FROM sc WHERE sc.sid<>'01' 
AND sc.cid IN(SELECT sc.cid FROM sc sc WHERE sc.sid='01')
GROUP BY sc.sid HAVING COUNT(*)=(SELECT COUNT(*) FROM sc WHERE sc.sid='01'))

SELECT * FROM student s WHERE 
s.sid IN(SELECT sc.sid FROM sc WHERE sc.sid<>'06' 
AND sc.cid IN(SELECT sc.cid FROM sc sc WHERE sc.sid='06')
GROUP BY sc.sid HAVING COUNT(*)=(SELECT COUNT(*) FROM sc WHERE sc.sid='06'))
-- ref
SELECT Student.* FROM Student WHERE 
SID IN(SELECT DISTINCT SC.SID FROM SC WHERE SID <> '01' 
AND SC.CID IN (SELECT DISTINCT CID FROM SC WHERE SID = '01')
GROUP BY SC.SID HAVING COUNT(1) = (SELECT COUNT(1) FROM SC WHERE SID='01'))

SELECT Student.* FROM Student WHERE 
SID IN(SELECT DISTINCT SC.SID FROM SC WHERE SID <> '06' 
AND SC.CID IN (SELECT DISTINCT CID FROM SC WHERE SID = '06')
GROUP BY SC.SID HAVING COUNT(1) = (SELECT COUNT(1) FROM SC WHERE SID='06'))


-- 14、查询没学过"张三"老师讲授的任一门课程的学生姓名
-- 查询张三老师教授课程的ID
SELECT * FROM course c WHERE c.tid = (SELECT tid FROM teacher WHERE tname = '张三') 
SELECT c.cid FROM course c WHERE c.tid = (SELECT tid FROM teacher WHERE tname = '张三') 
-- 查询学过此课程的学生id
SELECT * FROM sc sc WHERE sc.cid IN (SELECT c.cid FROM course c WHERE c.tid = (SELECT tid FROM teacher WHERE tname = '张三') )
SELECT sc.sid FROM sc sc WHERE sc.cid IN (SELECT c.cid FROM course c WHERE c.tid = (SELECT tid FROM teacher WHERE tname = '张三') )
-- 取反 得到没有学过此课程的学生信息
SELECT * FROM student s WHERE s.sid NOT IN (SELECT sc.sid FROM sc sc WHERE sc.cid IN (SELECT c.cid FROM course c WHERE c.tid = (SELECT tid FROM teacher WHERE tname = '张三'))) 

SELECT * FROM student s WHERE s.sid NOT IN 
(SELECT sc.sid FROM sc sc WHERE sc.cid IN 
(SELECT c.cid FROM course c WHERE c.tid = 
(SELECT tid FROM teacher WHERE tname = '张三'))) 

-- 改进 都是单表查询 效率太低
-- 三表关联查询 去除迪卡尔集
SELECT * FROM teacher t,course c,sc sc WHERE t.tid=c.tid AND c.cid=sc.cid
-- AND 条件并列 与先后顺序无关
SELECT * FROM teacher t,course c,sc sc WHERE t.tid=c.tid AND c.cid=sc.cid AND t.tname='张三'
SELECT * FROM teacher t,course c,sc sc WHERE t.tname='张三' AND t.tid=c.tid AND c.cid=sc.cid
-- 查询没学过"张三"老师讲授的任一门课程的学生姓名
SELECT * FROM student WHERE sid NOT IN(SELECT sc.sid FROM teacher t,course c,sc sc WHERE t.tid=c.tid AND c.cid=sc.cid AND t.tname='张三')

SELECT * FROM student WHERE sid NOT IN
(SELECT sc.sid FROM teacher t,course c,sc sc 
WHERE t.tid=c.tid AND c.cid=sc.cid AND t.tname='张三')

-- ref 
SELECT student.* FROM student WHERE student.SID NOT IN
(SELECT DISTINCT sc.SID FROM sc , course , teacher 
WHERE sc.CID = course.CID AND course.TID = teacher.TID AND teacher.tname = '张三')
ORDER BY student.SID

-- 15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
-- 查询不及格的课程
SELECT * FROM sc sc WHERE sc.score<60
-- 查询不及格的课程的学生ID
SELECT DISTINCT sc.sid FROM sc sc WHERE sc.score<60

-- 查询不及格课程的数目
SELECT DISTINCT sc.sid,COUNT(*) FROM sc sc WHERE sc.score<60 GROUP BY sc.sid

-- 查询不及格课程的数目大于等于二
SELECT DISTINCT sc.sid FROM sc sc WHERE sc.score<60 GROUP BY sc.sid
HAVING COUNT(*)>='2'

-- 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT s.sid,s.sname,AVG(sc.score) FROM student s,sc sc WHERE s.sid=sc.sid
AND s.sid IN(SELECT DISTINCT sc.sid FROM sc sc WHERE sc.score<60 GROUP BY sc.sid
HAVING COUNT(*)>='2') GROUP BY s.sid
-- 改进
SELECT *,AVG(sc.score) FROM student s,sc sc WHERE s.sid=sc.sid
AND sc.score<60 GROUP BY s.sid
HAVING COUNT(*)>='2' 

-- ref
SELECT student.SID , student.sname , CAST(AVG(score) AS DECIMAL(18,2)) avg_score 
FROM student , sc WHERE student.SID = SC.SID 
AND student.SID IN (SELECT SID FROM SC WHERE score < 60 GROUP BY SID 
HAVING COUNT(1) >= 2)GROUP BY student.SID , student.sname


-- 16、检索"01"课程分数小于60,按分数降序排列的学生信息
-- 检索"01"课程分数小于60
SELECT * FROM sc sc WHERE sc.cid='01' AND sc.score<60
-- 检索"01"课程分数小于60的学生ID
SELECT DISTINCT sc.sid FROM sc sc WHERE sc.cid='01' AND sc.score<60

-- 检索"01"课程分数小于60,按分数降序排列的学生信息
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01' 
AND s.sid IN(SELECT DISTINCT sc.sid FROM sc sc WHERE sc.cid='01' AND sc.score<60) 
ORDER BY sc.score DESC 

-- 改进
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid AND sc.cid='01' AND sc.score<60
ORDER BY sc.score DESC 

-- ref
SELECT student.* , sc.CID , sc.score FROM student , sc
WHERE student.SID = SC.SID AND sc.score < 60 AND sc.CID = '01'
ORDER BY sc.score DESC

-- 17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
-- 学生成绩
SELECT * FROM student s,sc sc,course c WHERE s.sid=sc.sid AND sc.cid=c.cid
-- 改进
-- 所有学生包括没有成绩的学生,应用外连接
-- 查询所有
SELECT * FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
LEFT JOIN course c ON sc.cid=c.cid

-- 列转行
-- 查询学生的所有成绩

SELECT * ,
(CASE c.cname WHEN '语文' THEN sc.score ELSE NULL END) 语文
FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
LEFT JOIN course c ON sc.cid=c.cid

SELECT * ,
(CASE c.cname WHEN '语文' THEN sc.score ELSE NULL END) 语文,
(CASE c.cname WHEN '数学' THEN sc.score ELSE NULL END) 数学,
(CASE c.cname WHEN '英语' THEN sc.score ELSE NULL END) 英语
FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
LEFT JOIN course c ON sc.cid=c.cid
-- 查询学生的所有成绩和平均成绩
SELECT * ,
(CASE c.cname WHEN '语文' THEN sc.score ELSE NULL END) 语文,
(CASE c.cname WHEN '数学' THEN sc.score ELSE NULL END) 数学,
(CASE c.cname WHEN '英语' THEN sc.score ELSE NULL END) 英语,
AVG(sc.score) avg_score
FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
LEFT JOIN course c ON sc.cid=c.cid
GROUP BY s.sid
-- 分析结果 分组之后 成绩为分组字段的第一条记录
-- case when实现行列转换时会出现多条记录
-- 如果不用聚合函数直接进行group by分组
-- 那么检索的是基表里分组字段的第一条记录
-- 如果使用max()函数之后再进行group by分组
-- 那么就会检索每个字段的最大值然后再分组
-- 改进
SELECT * ,
MAX(CASE c.cname WHEN '语文' THEN sc.score ELSE NULL END) 语文,
MAX(CASE c.cname WHEN '数学' THEN sc.score ELSE NULL END) 数学,
MAX(CASE c.cname WHEN '英语' THEN sc.score ELSE NULL END) 英语,
AVG(sc.score) avg_score
FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
LEFT JOIN course c ON sc.cid=c.cid
GROUP BY s.sid
-- 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
SELECT * ,
MAX(CASE c.cname WHEN '语文' THEN sc.score ELSE NULL END) 语文,
MAX(CASE c.cname WHEN '数学' THEN sc.score ELSE NULL END) 数学,
MAX(CASE c.cname WHEN '英语' THEN sc.score ELSE NULL END) 英语,
AVG(sc.score) avg_score
FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
LEFT JOIN course c ON sc.cid=c.cid
GROUP BY s.sid
ORDER BY avg_score DESC
-- 美化排版
SELECT s.sid,s.sname,
MAX(CASE c.cname WHEN '语文' THEN sc.score ELSE NULL END) 语文,
MAX(CASE c.cname WHEN '数学' THEN sc.score ELSE NULL END) 数学,
MAX(CASE c.cname WHEN '英语' THEN sc.score ELSE NULL END) 英语,
CAST(AVG(sc.score) AS DECIMAL(18,2)) avg_score
FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
LEFT JOIN course c ON sc.cid=c.cid
GROUP BY s.sid
ORDER BY avg_score DESC

-- 方式二
SELECT s.sid,s.sname,
MAX(CASE WHEN c.cname='语文' THEN sc.score ELSE NULL END) 语文,
MAX(CASE WHEN c.cname='数学' THEN sc.score ELSE NULL END) 数学,
MAX(CASE WHEN c.cname='英语' THEN sc.score ELSE NULL END) 英语,
CAST(AVG(sc.score) AS DECIMAL(18,2)) avg_score
FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
LEFT JOIN course c ON sc.cid=c.cid
GROUP BY s.sid
ORDER BY avg_score DESC 

-- ref 
SELECT a.SID 学生编号 , a.Sname 学生姓名 ,
MAX(CASE c.Cname WHEN '语文' THEN b.score ELSE NULL END)  语文,
MAX(CASE c.Cname WHEN '数学' THEN b.score ELSE NULL END)  数学,
MAX(CASE c.Cname WHEN '英语' THEN b.score ELSE NULL END)  英语 ,
CAST(AVG(b.score) AS DECIMAL(18,2)) avgscore FROM Student a
LEFT JOIN SC b ON a.SID = b.SID
LEFT JOIN Course c ON b.CID = c.CID
GROUP BY a.SID , a.Sname
ORDER BY avgscore DESC


-- ref
-- 17.1 SQL 2000 静态
SELECT a.SID 学生编号 , a.Sname 学生姓名 ,
       MAX(CASE c.Cname WHEN '语文' THEN b.score ELSE NULL END)  语文 ,
       MAX(CASE c.Cname WHEN '数学' THEN b.score ELSE NULL END)  数学 ,
       MAX(CASE c.Cname WHEN '英语' THEN b.score ELSE NULL END)  英语 ,
       CAST(AVG(b.score) AS DECIMAL(18,2)) 平均分
FROM Student a
LEFT JOIN SC b ON a.SID = b.SID
LEFT JOIN Course c ON b.CID = c.CID
GROUP BY a.SID , a.Sname
ORDER BY 平均分 DESC

SELECT a.SID 学生编号 , a.Sname 学生姓名 ,
MAX(CASE c.Cname WHEN '语文' THEN b.score ELSE NULL END)  语文,
MAX(CASE c.Cname WHEN '数学' THEN b.score ELSE NULL END)  数学,
MAX(CASE c.Cname WHEN '英语' THEN b.score ELSE NULL END)  英语 ,
CAST(AVG(b.score) AS DECIMAL(18,2)) avgscore FROM Student a
LEFT JOIN SC b ON a.SID = b.SID
LEFT JOIN Course c ON b.CID = c.CID
GROUP BY a.SID , a.Sname
ORDER BY avgscore DESC


-- 18、查询各科成绩最高分、最低分和平均分:以如下形式显示:
-- 课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
-- 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90

-- 查询所有学生的课程成绩
SELECT * FROM course c LEFT JOIN sc sc ON sc.cid=c.cid
-- 语文成绩
SELECT * FROM course c LEFT JOIN sc sc ON sc.cid=c.cid AND c.cname='语文'
-- 将成绩按科目分组
SELECT c.cid 课程序列, c.cname 课程名
FROM course c  LEFT JOIN sc sc ON sc.cid=c.cid
GROUP BY c.cid
-- 统计
SELECT c.cid 课程序列, c.cname 课程名 ,
MAX(sc.score) 最高分,MIN(sc.score) 最低分,AVG(sc.score) 平均分,
FROM course c  LEFT JOIN sc sc ON sc.cid=c.cid
GROUP BY c.cid
-- 做不下去了 换思路

-- 方法二

-- 所有成绩
SELECT * FROM course c,sc sc WHERE sc.cid=c.cid 
-- 语文成绩
SELECT * FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文'
SELECT sc.score FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文'
-- 各分段的成绩的成绩
SELECT sc.score FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文'
SELECT sc.score FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=60
SELECT sc.score FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=70 AND sc.score<=80 
SELECT sc.score FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=80 AND sc.score<=90
SELECT sc.score FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=90

-- 各分段的成绩的人数
SELECT COUNT(*) FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文'
SELECT COUNT(*) FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=60
SELECT COUNT(*) FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=70 AND sc.score<=80 
SELECT COUNT(*) FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=80 AND sc.score<=90
SELECT COUNT(*) FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=90

-- 及格率
SELECT c.cid 课程序列, c.cname 课程名 ,
MAX(sc.score) 最高分,MIN(sc.score) 最低分,AVG(sc.score) 平均分,
(SELECT COUNT(*) FROM course c,sc sc WHERE sc.cid=c.cid AND c.cname='语文' AND sc.score>=60) 及格人数
FROM course c ,sc sc WHERE sc.cid=c.cid
GROUP BY c.cid
-- 改进
-- 及格人数
SELECT c.cid 课程序列, c.cname 课程名 ,
MAX(sc.score) 最高分,MIN(sc.score) 最低分,AVG(sc.score) 平均分,
(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=60) 及格人数
FROM course c ,sc sc WHERE sc.cid=c.cid
GROUP BY c.cid
-- 总人数 
SELECT c.cid 课程序列, c.cname 课程名 ,
MAX(sc.score) 最高分,MIN(sc.score) 最低分,AVG(sc.score) 平均分,
(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid) 总人数
FROM course c ,sc sc WHERE sc.cid=c.cid
GROUP BY c.cid
-- 及格率
SELECT c.cid 课程序列, c.cname 课程名 ,
MAX(sc.score) 最高分,MIN(sc.score) 最低分,AVG(sc.score) 平均分,
(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=60)/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid) 及格率
FROM course c ,sc sc WHERE sc.cid=c.cid
GROUP BY c.cid

-- 课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
SELECT c.cid 课程序列, c.cname 课程名 ,
MAX(sc.score) 最高分,MIN(sc.score) 最低分,AVG(sc.score) 平均分,
(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=60)/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid) 及格率,
(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=70 AND sc2.score<=80)/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid) 中等率,
(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=80 AND sc2.score<=90)/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid) 优良率,
(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=90)/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid) 优秀率
FROM course c ,sc sc WHERE sc.cid=c.cid
GROUP BY c.cid

-- 优化  sc2.score<=80 sc2.score<80 sc2.score<=90 sc2.score<90
SELECT c.cid 课程序列, 
c.cname 课程名 ,
MAX(sc.score) 最高分,
MIN(sc.score) 最低分,
CAST(AVG(sc.score) AS DECIMAL(18,2)) 平均分,
CAST((SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=60)*100/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid)AS DECIMAL(18,2)) 及格率,
CAST((SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=70 AND sc2.score<80)*100/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid)AS DECIMAL(18,2)) 中等率,
CAST((SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=80 AND sc2.score<90)*100/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid)AS DECIMAL(18,2)) 优良率,
CAST((SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid  AND sc2.score>=90)*100/(SELECT COUNT(*) FROM sc sc2 WHERE sc2.cid=sc.cid)AS DECIMAL(18,2)) 优秀率
FROM course c ,sc sc WHERE sc.cid=c.cid
GROUP BY c.cid


-- ref
-- 方法1
-- 在两张表(课程表 成绩表)的交叉查询下 新增第三张表(成绩表) 用于过滤成绩
SELECT m.CID  课程编号 , m.Cname  课程名称 , 
  MAX(n.score)  最高分 ,
  MIN(n.score)  最低分 ,
  CAST(AVG(n.score) AS DECIMAL(18,2))  平均分 ,
  CAST((SELECT COUNT(1) FROM SC WHERE CID = m.CID AND score >= 60)*100.0 / (SELECT COUNT(1) FROM SC WHERE CID = m.CID) AS DECIMAL(18,2))  及格率 ,
  CAST((SELECT COUNT(1) FROM SC WHERE CID = m.CID AND score >= 70 AND score < 80 )*100.0 / (SELECT COUNT(1) FROM SC WHERE CID = m.CID) AS DECIMAL(18,2))  中等率 ,
  CAST((SELECT COUNT(1) FROM SC WHERE CID = m.CID AND score >= 80 AND score < 90 )*100.0 / (SELECT COUNT(1) FROM SC WHERE CID = m.CID) AS DECIMAL(18,2))  优良率 ,
  CAST((SELECT COUNT(1) FROM SC WHERE CID = m.CID AND score >= 90)*100.0 / (SELECT COUNT(1) FROM SC WHERE CID = m.CID) AS DECIMAL(18,2))  优秀率 
FROM Course m , SC n
WHERE m.CID = n.CID
GROUP BY m.CID , m.Cname
ORDER BY m.CID
 
-- 方法2 
-- 在单表(课程表)查询的基础上 增加一张成绩表 用于过滤成绩 更为简洁 WHERE CID = m.CID  相当于 GROUP BY m.CID
SELECT m.CID  课程编号 , m.Cname  课程名称 , 
  (SELECT MAX(score) FROM SC WHERE CID = m.CID)  最高分 ,
  (SELECT MIN(score) FROM SC WHERE CID = m.CID)  最低分 ,
  (SELECT CAST(AVG(score) AS DECIMAL(18,2)) FROM SC WHERE CID = m.CID)  平均分 ,
  CAST((SELECT COUNT(1) FROM SC WHERE CID = m.CID AND score >= 60)*100.0 / (SELECT COUNT(1) FROM SC WHERE CID = m.CID) AS DECIMAL(18,2))  及格率,
  CAST((SELECT COUNT(1) FROM SC WHERE CID = m.CID AND score >= 70 AND score < 80 )*100.0 / (SELECT COUNT(1) FROM SC WHERE CID = m.CID) AS DECIMAL(18,2))  中等率 ,
  CAST((SELECT COUNT(1) FROM SC WHERE CID = m.CID AND score >= 80 AND score < 90 )*100.0 / (SELECT COUNT(1) FROM SC WHERE CID = m.CID) AS DECIMAL(18,2))  优良率 ,
  CAST((SELECT COUNT(1) FROM SC WHERE CID = m.CID AND score >= 90)*100.0 / (SELECT COUNT(1) FROM SC WHERE CID = m.CID) AS DECIMAL(18,2))  优秀率
FROM Course m 
ORDER BY m.CID

-- 举例分析

SELECT * FROM sc WHERE sc.cid=01 

SELECT *, 
(SELECT MAX(sc.score) FROM sc WHERE sc.cid=1) 语文最高分
FROM course c

SELECT *, 
(SELECT MAX(sc.score) FROM sc WHERE sc.cid=2) 数学最高分
FROM course c

SELECT *, 
(SELECT MAX(sc.score) FROM sc WHERE sc.cid=3) 外语最高分
FROM course c

SELECT *, 
(SELECT MAX(sc.score) FROM sc WHERE sc.cid=c.cid) 各科最高分
FROM course c 

SELECT *, 
(SELECT MAX(sc.score) FROM sc WHERE sc.cid=c.cid AND c.cname='语文') 语文最高分
FROM course c 

-- 查询语文最高分
SELECT *,(SELECT MAX(sc.score) FROM sc sc WHERE sc.cid=c.cid AND c.cname='语文') 
FROM course c
-- 各科最高分
SELECT *,(SELECT MAX(sc.score) FROM sc sc WHERE sc.cid=c.cid) 
FROM course c


-- 19、按各科成绩进行排序,并显示排名

-- 查询所有
SELECT * FROM sc sc,course c WHERE sc.cid=c.cid

-- 查询语文成绩
SELECT *,sc.score 语文
FROM sc sc,course c WHERE sc.cid=c.cid AND c.cname='语文'
ORDER BY sc.score DESC

-- 单表查询语文成绩
SELECT * FROM sc sc WHERE sc.cid=01

SELECT *,sc.score 语文,
(SELECT COUNT(*) FROM sc sc2 
WHERE sc2.score>sc.score AND sc2.cid=c.cid)+1 rank
FROM sc sc,course c WHERE sc.cid=c.cid AND c.cname='语文'
ORDER BY sc.score DESC


-- ref
--Score重复时保留名次空缺
SELECT t.* , px = (SELECT COUNT(1) FROM SC WHERE CID = t.CID AND score > t.score) + 1 FROM sc t ORDER BY t.cid , px 
--Score重复时合并名次
SELECT t.* , px = (SELECT COUNT(DISTINCT score) FROM SC WHERE CID = t.CID AND score >= t.score) FROM sc t ORDER BY t.cid , px 

-- 方式二 
-- 为什么这样写结果跟预期的不一样呢
SET @rank:=0;
SELECT *,sc.score 语文,
@rank:=@rank+1 AS rank
FROM sc sc,course c 
WHERE sc.cid=c.cid AND c.cname='语文'
ORDER BY sc.score DESC

-- 这样写得不到排名的原因分析
-- 先执行
SET @rank:=0;
SELECT *,sc.score 语文,
@rank:=@rank+1 AS rank
FROM sc sc,course c 
WHERE sc.cid=c.cid AND c.cname='语文'
-- 执行结果 rank的值即为查询的顺序 rank已经取值
-- 再执行
SET @rank:=0;
SELECT *,sc.score 语文,
@rank:=@rank+1 AS rank
FROM sc sc,course c 
WHERE sc.cid=c.cid AND c.cname='语文'
ORDER BY sc.score DESC
-- rank的值并没有改变 只是随着成绩排序改变了位置
-- 观察结果对比
-- SQL的执行顺序是先查询,再排序
-- 所以变量的值即为查询的顺序


-- 20、查询学生的总成绩并进行排名
-- 查询学生的成绩
SELECT * FROM student s,sc sc WHERE s.sid=sc.sid

SELECT * FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
-- 查询学生的总成绩
SELECT *,SUM(sc.score) total_score FROM student s,sc sc WHERE s.sid=sc.sid
GROUP BY s.sid

-- 学生的总成绩降序排列
SELECT *,SUM(sc.score) total_score FROM student s LEFT JOIN sc sc ON s.sid=sc.sid
GROUP BY s.sid
ORDER BY total_score DESC
-- 学生的总成绩
SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC

-- 学生的总成绩排名
-- 排名思路 这条记录的总成绩与所有记录总成绩比较 统计数量作为排名

-- 1.创建第一张记录学生ID,姓名与总成绩的表t1,作为基表

SELECT * FROM () t1

SELECT * FROM
(SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC) t1

-- 2.在基表上筛选 创建第二张记录学生ID,姓名与总成绩的表t2,作为临时表,与基表比较
-- 这里t2表的所有记录的总成绩会与t1表当前记录的总成绩比较 得到数量 拼接到当前记录(当前行)的rank字段
-- 可以理解为表记录也是一行一行查出来的,实际上rank与前面的字段本来就是并列的
SELECT *,(SELECT COUNT(1) FROM () t2 WHERE t2.total_score>t1.total_score)rank FROM () t1

SELECT *,(
SELECT COUNT(1) FROM (
SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC
) t2 WHERE t2.total_score>t1.total_score
)rank 
FROM (SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC) t1

-- 3.将结果rank排序
SELECT *,(SELECT COUNT(1) FROM () t2 WHERE t2.total_score>t1.total_score)rank FROM () t1 ORDER BY rank DESC

SELECT *,(
SELECT COUNT(1) FROM (
SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC
) t2 WHERE t2.total_score>t1.total_score
) rank 
FROM (SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC) t1
ORDER BY rank 
-- 其实由于t1,t2表的总成绩已经排序 这里rank其实不再需要排序 但这样效率较低

-- 优化t1,t2表的总成绩不需要排序 最后排序即可 
-- t2 表不需要学生ID和姓名
-- -- 分数重复时保留名次空缺
SELECT t1.*,(
SELECT COUNT(t2.total_score) FROM (
SELECT IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid) t2 WHERE t2.total_score>t1.total_score
)+1 rank 
FROM (
SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid) t1
ORDER BY rank 

-- 分数重复时合并名次
SELECT t1.*,(
SELECT COUNT(DISTINCT t2.total_score) FROM (
SELECT IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid) t2 WHERE t2.total_score>t1.total_score
)+1 rank 
FROM (
SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid) t1
ORDER BY rank 


-- 方式二

-- 错误写法
SET @rank:=0;
SELECT *,SUM(sc.score) total_score,@rank:=@rank+1 rank FROM student s
LEFT JOIN sc sc ON s.sid=sc.sid
GROUP BY s.sid
ORDER BY total_score DESC
-- 这样写得不到排名的原因分析
SET @rank:=0;
SELECT *,SUM(sc.score) total_score,@rank:=@rank+1 rank FROM student s
LEFT JOIN sc sc ON s.sid=sc.sid
GROUP BY s.sid
-- 分开执行
SET @rank:=0;
SELECT *,SUM(sc.score) total_score,@rank:=@rank+1 rank FROM student s
LEFT JOIN sc sc ON s.sid=sc.sid
GROUP BY s.sid
ORDER BY total_score DESC

-- 正确写法
SET @rank:=0;
SELECT *, @rank:=@rank+1 rank 
FROM (SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC) t1


-- 普通排名 12345
-- 为了初始化变量rank 新建了一张表 t3
SELECT t1.*, @rank:=@rank+1 AS rank 
FROM (SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC) t1,(SELECT @rank := 0) t3

-- 分数重复时合并名次 1 2 2 3 4
SELECT t1.*, 
CASE 
WHEN @prevRank = total_score THEN @curRank 
WHEN @prevRank := total_score THEN @curRank := @curRank + 1
END AS rank
FROM (SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC) t1,(SELECT @curRank :=0, @prevRank := NULL) t3

-- 分数重复时保留名次空缺 1 2 2 4 5 

SELECT *,rank FROM
(SELECT t1.*,
@curRank := IF(@prevRank = total_score, @curRank, @incRank) AS rank, 
@incRank := @incRank + 1, 
@prevRank := total_score
FROM (SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC) t1, (SELECT @curRank :=0, @prevRank := NULL, @incRank := 1) r 
) s


SELECT sid,sname,total_score,rank FROM
(SELECT t1.*,
@curRank := IF(@prevRank = total_score, @curRank, @incRank) AS rank, 
@incRank := @incRank + 1, 
@prevRank := total_score
FROM (SELECT s.sid,s.sname,IFNULL(SUM(sc1.score),0) total_score FROM student s LEFT JOIN sc sc1 ON s.sid=sc1.sid
GROUP BY s.sid
ORDER BY total_score DESC) t1, (SELECT @curRank :=0, @prevRank := NULL, @incRank := 1) r 
) s


-- ref
-- 分数重复时保留名次空缺
SELECT t1.*, 
(
	SELECT COUNT(1) FROM 
	(
	  SELECT m.SID  学生编号  , 
			 m.Sname  学生姓名  ,
			 IFNULL(SUM(score),0)  总成绩 
	  FROM Student m LEFT JOIN SC n ON m.SID = n.SID 
	  GROUP BY m.SID , m.Sname
	) t2 WHERE 总成绩 > t1.总成绩
)+1 rank
FROM 
(
  SELECT m.SID  学生编号  , 
         m.Sname  学生姓名  ,
         IFNULL(SUM(score),0)  总成绩 
  FROM Student m LEFT JOIN SC n ON m.SID = n.SID 
  GROUP BY m.SID , m.Sname
) t1
ORDER BY rank

-- 分数重复时合并名次
SELECT t1.*, 
(
	SELECT COUNT(DISTINCT 总成绩) FROM 
	(
	  SELECT m.SID  学生编号, m.Sname  学生姓名,IFNULL(SUM(score),0)  总成绩 
	  FROM Student m LEFT JOIN SC n ON m.SID = n.SID 
	  GROUP BY m.SID , m.Sname
	) t2 WHERE 总成绩 >= t1.总成绩
)rank 
FROM 
(
  SELECT m.SID  学生编号, m.Sname 学生姓名,IFNULL(SUM(score),0)  总成绩 
  FROM Student m LEFT JOIN SC n ON m.SID = n.SID 
  GROUP BY m.SID , m.Sname
) t1
ORDER BY rank

-- 21、查询不同老师所教不同课程平均分从高到低显示
-- 查询不同老师所教的课程
SELECT * FROM teacher t,course c,sc sc1 WHERE t.tid=c.tid AND c.cid=sc1.cid ORDER BY t.tid
-- 查询不同老师所交不同课程的平均分 
SELECT t.tid,t.tname,AVG(score) avg_score FROM teacher t,course c,sc sc1 
WHERE t.tid=c.tid AND c.cid=sc1.cid GROUP BY t.tid ORDER BY avg_score DESC

-- ref 
SELECT m.TID , m.Tname , CAST(AVG(o.score) AS DECIMAL(18,2)) avg_score
FROM Teacher m , Course n , SC o
WHERE m.TID = n.TID AND n.CID = o.CID
GROUP BY m.TID , m.Tname
ORDER BY avg_score DESC

-- 22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩

-- 1.查询
-- 1.查询所有需要的信息(学生表 课程表 成绩表)作为基础表 注意:基础表的列名不能相同 否则从基础表拿数据会冲突
SELECT * FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid
SELECT * FROM student s LEFT JOIN sc sc ON s.sid=sc.sid LEFT JOIN course c ON c.cid=sc.cid
-- 2.筛选
-- 2.1 筛选指定课程信息
SELECT * FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文'
-- 2.1 指定课程排序
SELECT * FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文'
ORDER BY sc.score DESC 
-- 2.1 指定课程排名
-- 产生名次
-- 思路-伪SQL
SELECT COUNT() FROM () t1 WHERE t1.score>b1.score
SELECT *,() rank FROM () b1

-- 方式一
-- 1 1 3 4 5
SELECT b1.sid,b1.sname,b1.cname,b1.score,
(SELECT COUNT(*) FROM (SELECT score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文') t1 WHERE t1.score>b1.score)+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文' 
ORDER BY sc.score DESC ) b1
-- 1 1 2 3 4 
SELECT b1.sid,b1.sname,b1.cname,b1.score,
(SELECT COUNT(DISTINCT score) FROM (SELECT score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文') t1 WHERE t1.score>b1.score)+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文' 
ORDER BY sc.score DESC ) b1

-- 方式二
-- 1 2 3 4 5
SET @rank:=0;
SELECT b1.sid,b1.sname,b1.cname,b1.score,
@rank:=@rank+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文' 
ORDER BY sc.score DESC ) b1
-- 1 2 3 4 5
SELECT b1.sid,b1.sname,b1.cname,b1.score,
@rank:=@rank+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文' 
ORDER BY sc.score DESC ) b1,(SELECT @rank:=0) p

-- 2.2 第2名到第3名的学生信息及该课程成绩
SELECT * FROM() t2 WHERE rank<4 AND rank >1

SELECT * FROM(SELECT b1.sid,b1.sname,b1.cname,b1.score,
(SELECT COUNT(DISTINCT score) FROM (SELECT score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文') t1 WHERE t1.score>b1.score)+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文' 
ORDER BY sc.score DESC ) b1) t2 WHERE rank<4 AND rank >1

SELECT * FROM(SELECT b1.sid,b1.sname,b1.cname,b1.score,
@rank:=@rank+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文' 
ORDER BY sc.score DESC ) b1,(SELECT @rank:=0) p) t2 WHERE rank<4 AND rank >1

-- 指定科目查出再查所有科目
-- 这种写法使用UNION ALL效率很低,有很多重复代码,纯手工打造,当科目很多时,根本无法手工列举
SELECT * FROM(SELECT b1.sid,b1.sname,b1.cname,b1.score,
@rank:=@rank+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文' 
ORDER BY sc.score DESC ) b1,(SELECT @rank:=0) p) t2 WHERE rank<4 AND rank >1
UNION ALL 
SELECT * FROM(SELECT b1.sid,b1.sname,b1.cname,b1.score,
@rank:=@rank+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '数学' 
ORDER BY sc.score DESC ) b1,(SELECT @rank:=0) p) t2 WHERE rank<4 AND rank >1
UNION ALL 
SELECT * FROM(SELECT b1.sid,b1.sname,b1.cname,b1.score,
@rank:=@rank+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '英语' 
ORDER BY sc.score DESC ) b1,(SELECT @rank:=0) p) t2 WHERE rank<4 AND rank >1

SELECT * FROM(SELECT b1.sid,b1.sname,b1.cname,b1.score,
(SELECT COUNT(DISTINCT score) FROM (SELECT score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文') t1 WHERE t1.score>b1.score)+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '语文' 
ORDER BY sc.score DESC ) b1) t2 WHERE rank<4 AND rank >1
union all 
SELECT * FROM(SELECT b1.sid,b1.sname,b1.cname,b1.score,
(SELECT COUNT(DISTINCT score) FROM (SELECT score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '数学') t1 WHERE t1.score>b1.score)+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '数学' 
ORDER BY sc.score DESC ) b1) t2 WHERE rank<4 AND rank >1
union all
SELECT * FROM(SELECT b1.sid,b1.sname,b1.cname,b1.score,
(SELECT COUNT(DISTINCT score) FROM (SELECT score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '英语') t1 WHERE t1.score>b1.score)+1 rank 
FROM (SELECT s.sid,sname,cname,score FROM student s,course c,sc sc WHERE s.sid=sc.sid AND c.cid=sc.cid AND c.cname = '英语' 
ORDER BY sc.score DESC ) b1) t2 WHERE rank<4 AND rank >1


-- 22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
-- 查询所有课程成绩
SELECT t.* FROM sc t
-- 将成绩按课程分类 然后排名
SELECT t.*,() rank FROM sc t
-- 使用order by cid 显然不行 我们是为了将产生的多个结果分类 而不是分组聚合之后只产生一个结果
-- 我们可以使用一张临时表 通过 sc.cid = t.cid 达到分类的效果
-- Operand should contain 1 column(s)
-- 我们想查出排名这一列(字段),所以不能返多列(字段)
SELECT t.*,(
SELECT * FROM sc WHERE sc.cid= t.cid 
) rank FROM sc t
-- Subquery returns more than 1 row
-- rank与前面的数据组成一行(记录) 所以不能返回一列 
-- 可以把SQL理解为一个函数 select后的是函数的返回值 from和where组成参数参数列表
SELECT t.*,(
SELECT cid FROM sc WHERE sc.cid= t.cid 
) rank FROM sc t
-- 只能返回一个数据
SELECT t.*,(
SELECT COUNT(1) FROM sc WHERE sc.cid= t.cid 
) rank FROM sc t

-- 排名
-- 产生名次
SELECT t.*,(
SELECT COUNT(1) FROM sc WHERE sc.cid= t.cid AND sc.score>t.score
) rank FROM sc t
-- 按名次排序
SELECT * FROM () t2 
-- 先按cid 排序 cid相同再按rank排序
SELECT * FROM () t2 ORDER BY t2.cid,t2.rank

SELECT * FROM (
SELECT t.*,(SELECT COUNT(1) FROM sc WHERE sc.cid= t.cid AND sc.score>t.score) rank FROM sc t
) t2 ORDER BY t2.cid,t2.rank

-- 筛选出2到3名

SELECT * FROM () t3 WHERE t3.rank BETWEEN 2 AND 3

SELECT * FROM (SELECT * FROM (
SELECT t.*,(SELECT COUNT(1) FROM sc WHERE sc.cid= t.cid AND sc.score>t.score) rank FROM sc t
) t2 ORDER BY t2.cid,t2.rank
) t3 WHERE t3.rank BETWEEN 2 AND 3

-- 关联学生表 课程表 显示相关信息
SELECT * FROM () t4,student s,course c WHERE t4.sid=s.sid AND t4.cid = c.cid

SELECT sname,cname,t4.* FROM (SELECT * FROM (SELECT * FROM (
SELECT t.*,(SELECT COUNT(1) FROM sc WHERE sc.cid= t.cid AND sc.score>t.score) rank FROM sc t
) t2 ORDER BY t2.cid,t2.rank
) t3 WHERE t3.rank BETWEEN 2 AND 3) t4,student s,course c WHERE t4.sid=s.sid AND t4.cid = c.cid

-- 排序整理
SELECT sname,cname,t4.* FROM (SELECT * FROM (SELECT * FROM (
SELECT t.*,(SELECT COUNT(1) FROM sc WHERE sc.cid= t.cid AND sc.score>t.score) rank FROM sc t
) t2 ORDER BY t2.cid,t2.rank
) t3 WHERE t3.rank BETWEEN 2 AND 3) t4,student s,course c WHERE t4.sid=s.sid AND t4.cid = c.cid
ORDER BY t4.cid,t4.rank



-- ref 
SELECT (SELECT COUNT(1) FROM SC WHERE CID = t.CID AND score > t.score) + 1 px FROM sc t 

SELECT t.* , (SELECT COUNT(1) FROM SC WHERE CID = t.CID AND score > t.score) + 1 px FROM sc t 


SELECT * FROM 
(SELECT t.* , (SELECT COUNT(1) FROM SC WHERE CID = t.CID AND score > t.score) + 1 px FROM sc t) m 
WHERE px BETWEEN 2 AND 3 ORDER BY m.cid , m.px 

SELECT * FROM 
(SELECT t.* , (SELECT COUNT(DISTINCT score) FROM SC WHERE CID = t.CID AND score > t.score) + 1 px FROM sc t) m 
WHERE px BETWEEN 2 AND 3 ORDER BY m.cid , m.px 

SELECT * FROM student s,course c,() sc WHERE s.sid=sc.sid AND c.cid=sc.cid

SELECT sname,cname,t2.* FROM student s,course c,(SELECT * FROM 
(SELECT t.* , (SELECT COUNT(DISTINCT score) FROM SC WHERE CID = t.CID AND score > t.score) + 1 px FROM sc t) m 
WHERE px BETWEEN 2 AND 3 ORDER BY m.cid , m.px ) t2 WHERE s.sid=t2.sid AND c.cid=t2.cid
ORDER BY t2.cid,t2.px


SELECT sname,cname,t2.* FROM student s,course c,(SELECT * FROM 
(
SELECT t.* , (SELECT COUNT(1) FROM SC WHERE CID = t.CID AND score > t.score) + 1 px FROM sc t 
ORDER BY t.cid , px ) m 
WHERE px BETWEEN 2 AND 3 ) t2 WHERE s.sid=t2.sid AND c.cid=t2.cid
ORDER BY t2.cid,t2.px

22.查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
思路
1产生排名 ==>t1
2查询第二名到第三名的成绩 ==>t2
3关联学生表,课程表与t2显示相关学生信息

1产生排名 ==>t1
select *,() rank from  sc sc2 order by sc2.cid,sc2.score desc

select *,(select count(score) from sc sc1 where sc1.cid=sc2.cid and sc1.score>sc2.score) rank from sc sc2 


2查询第二名到第三名的成绩 ==>t2
select * from () t1 where rank between 2 and 3

select * from (select *,(select count(score) from sc sc1 where sc1.cid=sc2.cid and sc1.score>sc2.score) rank from sc sc2) t1 where rank between 2 and 3 

3关联学生表,课程表与t2显示相关学生信息
select s.sname,c.cname,t2.* from student s ,course c,(select * from (select *,(select count(score) from sc sc1 where sc1.cid=sc2.cid and sc1.score>sc2.score) rank from sc sc2 ) t1 where rank between 2 and 3
) t2 where s.sid = t2.sid and c.cid = t2.cid order by t2.cid ,t2.rank







-- 23、统计各科成绩各分数段人数:课程编号,课程名称, 100-85 , 85-70 , 70-60 , 0-60 及所占百分比
课程编号,课程名称, 100-85 , 85-70 , 70-60 , 0-60 及所占百分比
思路
1.观察表结构需要新增多列,先统计各分段人数
2.再算出所占百分比
3.关联其它表增加更多列信息
1.观察表结构需要新增多列,先统计各分段人数
-- 查询所有成绩
select * from sc 
-- 增加列 统计各分段人数
select *,() 100-85 from sc 

select *,(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 85 and sc.score <= 100) '100-85' from sc sc1 
group by sc1.cid

select *,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score between 85 and 100) '100-85',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score between 70 and 85) '85-70',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score between 60 and 70) '70-60',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score between 0 and 60) '0-60'
from sc sc1 
group by sc1.cid

改进 between 85 and 100 相当于 sc.score >= 85 and sc.score <= 100 与下个分段会出现重复

select *,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 85) '100-85',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 70 and sc.score < 85) '85-70',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 60 and sc.score < 70) '70-60',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score < 60) '0-60'
from sc sc1 
group by sc1.cid

方式二(横向)

select sc.* from sc group by sc.cid

select *,
sum(case when sc.score >= 85 then 1 else 0 end) `100-85`
from sc group by sc.cid

select sc.cid,
sum(case when sc.score >= 85  then 1 else 0 end) `85-100`,
sum(case when sc.score >= 70 and sc.score < 85 then 1 else 0 end) `70-85`,
sum(case when sc.score >= 60 and sc.score < 70 then 1 else 0 end) `60-70`,
sum(case when sc.score < 60 then 1 else 0 end) `0-60`
from sc group by sc.cid

方式三(纵向)
select sc.*,sc.cid `课程编号`,course.cname `课程名称`,
case 
	when sc.score >= 85 then '85-100人数'
	when sc.score >= 70 and sc.score <= 85 then '70-85人数'
	when sc.score >= 60 and sc.score <= 70 then '60-70人数'
	else '0-60人数' 
end
from sc left join course on sc.cid = course.cid

select sc.cid `课程编号`,course.cname `课程名称`,
(case 
	when sc.score >= 85 then '85-100人数'
	when sc.score >= 70 and sc.score <= 85 then '70-85人数'
	when sc.score >= 60 and sc.score <= 70 then '60-70人数'
	else '0-60人数' 
end) `分段`,
count(1)
from sc left join course on sc.cid = course.cid
group by
case 
	when sc.score >= 85 then '85-100人数'
	when sc.score >= 70 and sc.score <= 85 then '70-85人数'
	when sc.score >= 60 and sc.score <= 70 then '60-70人数'
	else '0-60人数' 
end,sc.cid
order by 
sc.cid,`分段`





2.再算出所占百分比
select sc1.cid,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 85) '100-85',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 85)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 70 and sc.score < 85) '85-70',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 70 and sc.score < 85)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 60 and sc.score < 70) '70-60',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 60 and sc.score < 70)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score < 60) '0-60',
(select count(sc.score) from sc where sc.cid = sc.score < 60)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100 百分比
from sc sc1
group by sc1.cid


3.关联其它表增加更多列信息

select sc1.cid,c.cname,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 85) '100-85',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 85)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 70 and sc.score < 85) '85-70',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 70 and sc.score < 85)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 60 and sc.score < 70) '70-60',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 60 and sc.score < 70)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score < 60) '0-60',
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score between 0 and 60)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100 百分比
from sc sc1 left join course c on sc1.cid=c.cid
group by sc1.cid


cast(() as decimal(5,2))


select sc1.cid,c.cname,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 85) '100-85',
cast(((select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 85)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100) as decimal(5,2)) 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 70 and sc.score < 85) '85-70',
cast(((select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 70 and sc.score < 85)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100) as decimal(5,2)) 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 60 and sc.score < 70) '70-60',
cast(((select count(sc.score) from sc where sc.cid = sc1.cid and sc.score >= 60 and sc.score < 70)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100) as decimal(5,2)) 百分比,
(select count(sc.score) from sc where sc.cid = sc1.cid and sc.score < 60) '0-60',
cast(((select count(sc.score) from sc where sc.cid = sc1.cid and sc.score between 0 and 60)/(select count(sc.score) from sc where sc.cid = sc1.cid)*100) as decimal(5,2)) 百分比
from sc sc1 left join course c on sc1.cid=c.cid
group by sc1.cid



--ref
select course.cid  课程编号  , cname 课程名称  ,
  sum(case when score >= 85 then 1 else 0 end)  `85-100` ,
  sum(case when score >= 70 and score < 85 then 1 else 0 end)  `70-85` ,
  sum(case when score >= 60 and score < 70 then 1 else 0 end)  `60-70` ,
  sum(case when score < 60 then 1 else 0 end)  `0-60`
from sc , course 
where sc.cid = course.cid 
group by course.cid , course.cname
order by course.cid


select m.cid  课程编号  , m.cname  课程名称  , (
  case when n.score >= 85 then '85-100'
       when n.score >= 70 and n.score < 85 then '70-85'
       when n.score >= 60 and n.score < 70 then '60-70'
       else '0-60'
  end) 分数段, 
  count(1) 数量 
from course m , sc n
where m.cid = n.cid 
group by m.cid , m.cname , (
  case when n.score >= 85 then '85-100'
       when n.score >= 70 and n.score < 85 then '70-85'
       when n.score >= 60 and n.score < 70 then '60-70'
       else '0-60'
  end)
order by m.cid , m.cname , 分数段




-- 24、查询学生平均成绩及其名次
思路
1.统计平均成绩=>t1
2.排名
3.关联学生表,显示相关信息
1.统计平均成绩 =>t1
select *,avg(sc.score) avg from sc sc group by sc.sid
select *,cast(avg(sc.score) as decimal(4,2)) avg from sc sc group by sc.sid
2.按平均成绩排名
方式一:
select count(score) from () t2 where t2.avg>t1.avg

select *,() rank from ()t1

select *,
(select count(avg) from (select cast(avg(sc.score) as decimal(4,2)) avg from sc sc group by sc.sid) t2 where t2.avg>t1.avg) rank 
from (select *,cast(avg(sc.score) as decimal(4,2)) avg from sc sc group by sc.sid)t1

方式二:
select * from ()
3.关联学生表,显示相关信息
select 
    s.sname,
		t1.sid,
    t1.avg,
    (select count(avg) from (select cast(avg(sc.score) as decimal(4,2)) avg from sc sc group by sc.sid) t2 where t2.avg>t1.avg)+1 rank 
from 
    (select *,cast(avg(sc.score) as decimal(4,2)) avg from sc sc group by sc.sid) t1 left join student s on t1.sid = s.sid
order by rank

-- ref 这是一个反面例子 内连接不加条件(相当于交叉连接) 会产生的笛卡尔积查询 加卡尔积是多表记录的乘积 这样数据量大 显然效率极低
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;
-- 内连接不加条件,相当于交叉连接,INNER JOIN 可以去去掉 下面的查询结果与上面是一样的
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,
(SELECT sid,avg(score) avg_score FROM SC GROUP BY sid) b
GROUP BY a.sid,
a.avg_score
ORDER BY scc;
-- 过程分析
SELECT a.*,b.*
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
-- (49 row(s) returned

SELECT a.*,b.*,
(CASE WHEN a.avg_score<b.avg_score THEN 1 ELSE 0 END) 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
-- (49 row(s) returned


-- 25、查询各科成绩前三名的记录
思路
1排名 =>t1
2选出前三名

1排名 =>t1
select *,() rank from sc s2

select *,(select count(s1.score) from sc s1 where s1.cid=s2.cid and s1.score>s2.score) rank from sc s2
2选出前三名
select * from () t1

select * from (select *,(select count(s1.score) from sc s1 where s1.cid=s2.cid and s1.score>s2.score) rank from sc s2) t1 where t1.rank<=3 order by t1.cid,t1.rank

-- ref
SELECT sc0.*,
            (SELECT count(1) FROM SC WHERE SC.cid=sc0.cid AND SC.score>sc0.score)+1 rank
    FROM SC sc0
GROUP BY 2,1,3
HAVING rank<=3
ORDER BY sc0.cid,rank;

-- 26、查询每门课程被选修的学生数
select *,count(sc.sid) amount from sc group by sc.cid


-- 27、查询出只有两门课程的全部学生的学号和姓名
思路
1统计学生选课数量=>t1
2找出只有两门课的学生
3关联
1统计学生选课数量=>t1
select *,count(sc.sid) amount from sc group by sc.sid
2找出只有两门课的学生
select * from () t1 where t1.amount = 2

select * from (select *,count(sc.sid) amount from sc group by sc.sid) t1 where t1.amount = 2

3关联
select s.sid,s.sname from (select *,count(sc.sid) amount from sc group by sc.sid) t1,student s 
where t1.amount = 2 and t1.sid = s.sid

-- 28、查询男生、女生人数
-- 横向
select () `男生人数`,() `女生人数` from student

select sum(case when s.ssex='男' then 1 else 0 end) `男生人数`,sum(case when s.ssex='女' then 1 else 0 end) `女生人数` from student s
-- 纵向
select () `性别`,() `人数` from student s

select (case when s.ssex = '男' then '男' else '女' end) `性别`,count(s.ssex) `人数` from student s
group by (case when s.ssex = '男' then '男' else '女' end)


-- 29、查询名字中含有"风"字的学生信息 
select * from student s where s.sname like '%风%'

-- 30、查询同名同性学生名单,并统计同名人数
-- 这里的1代表第一列,2代表第二列 直接写列名效果也是一样的
-- GROUP BY 1,2 的意思是先按第一列分组 第一列相同再按第二列分组 两列都相同就在同一组
-- 同名同姓人数
SELECT sname,ssex,count(1)
FROM Student GROUP BY 1,2 
HAVING count(1)>1;

SELECT sname,ssex,count(sname)
FROM Student GROUP BY sname,ssex 
HAVING count(sname)>1;
-- 同名人数
SELECT sname,ssex,count(1)
FROM Student GROUP BY 1 
HAVING count(1)>1;

SELECT sname,ssex,count(sname)
FROM Student GROUP BY sname
HAVING count(sname)>1;

-- 31、查询1990年出生的学生名单(注:Student表中Sage列的类型是datetime)
		SELECT Student.* FROM Student WHERE YEAR(sage)=1990;
hive

-- 32、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
统计每门课的平均成绩 按平均成绩排序
select cid,avg(sc.score) avg from sc group by sc.cid order by avg desc,cid

-- 33、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
1统计每个学生的平均成绩 =>t1
2选出大于85的平均成绩 =>t2
3关联学生表,显示相关信息

1统计每个学生的平均成绩 =>t1
select sid,avg(sc.score) avg from sc group by sc.sid	
2选出大于85的平均成绩 =>t2
select * from () t1 where t1.avg>=85

select * from (select sid,avg(sc.score) avg from sc group by sc.sid) t1 where t1.avg>=85
3关联学生表,显示相关信息
select * from () t2,student s where t2.sid = s.sid

select s.sid,s.sname,t2.avg from (select * from (select sid,avg(sc.score) avg from sc group by sc.sid) t1 where t1.avg>=85) t2,student s where t2.sid = s.sid
		
-- 34、查询课程名称为"数学",且分数低于60的学生姓名和分数
select s.sname,sc.score from course c,sc sc,student s where c.cid=sc.cid and sc.sid=s.sid and c.cname='数学' and sc.score < 60
hive

-- 35、查询所有学生的课程及分数情况;
select s.sname,c.cname,sc.score from course c,sc sc,student s where c.cid=sc.cid and sc.sid=s.sid

--36、查询任何一门课程成绩在70分以上的学生姓名、课程名称和分数;

-- 如果将任何一门成绩在70分以上,理解为所有成绩在70分以上的话
思路
1.查出每个学生的最小的成绩 => t1
2.选出最小的成绩比70大的学生,那么此学生的所有成绩都大于70 => t2
3.关联其它表,显示相关信息

1.查出每个学生的最小的成绩
select sid,min(score) min_score from sc group by sid

2.选出最小的成绩比70大的学生,那么此学生的所有成绩都大于70
select sid from () t1 where t1.min_score>70
select sid from (select sid,min(score) min_score from sc group by sid) t1 where t1.min_score>70

3.关联其它表,显示相关信息
select * from student s,sc sc,course c,() t2 where s.sid =sc.sid and sc.cid =c.cid and sc.sid = t2.sid

select 
    s.sname 学生姓名,c.cname 课程名,sc.score 分数 
from 
    student s,sc sc,course c,(select sid from (select sid,min(score) min_score from sc group by sid) t1 where t1.min_score>70) t2 
where 
	s.sid =sc.sid and sc.cid =c.cid and sc.sid = t2.sid
	
	
	
-- 如果将任何一门成绩在70分以上,理解为其中一门成绩在70分以上的话
思路
1.查出每个学生的最大的成绩 => t1
2.选出最大的成绩比70大的学生,那么此学生其中一门成绩大于70 => t2
3.关联其它表,显示相关信息

1.查出每个学生的最大的成绩
select sid,max(score) max_score from sc group by sid

2.选出最大的成绩比70大的学生,那么此学生其中一门成绩大于70 => t2
select sid from () t1 where t1.max_score>70
select sid from (select sid,max(score) max_score from sc group by sid) t1 where t1.max_score>70

3.关联其它表,显示相关信息
select * from student s,sc sc,course c,() t2 where s.sid =sc.sid and sc.cid =c.cid and sc.sid = t2.sid

select 
    s.sname 学生姓名,c.cname 课程名,sc.score 分数 
from 
    student s,sc sc,course c,(select sid from (select sid,max(score) max_score from sc group by sid) t1 where t1.max_score>70) t2 
where 
	s.sid =sc.sid and sc.cid =c.cid and sc.sid = t2.sid

-- 37、查询不及格的课程
select * from sc where sc.score<60
-- 38、查询课程编号为01且课程成绩在80分以上的学生的学号和姓名
select * from sc sc,student s where sc.sid=s.sid and sc.cid='01' and sc.score >= 80
-- 39、求每门课程的学生人数
select count(sc.sid) from  sc group by sc.cid
-- 40、查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩
select *,max(sc.score) from sc sc,course c,teacher t where sc.cid=c.cid and c.tid=t.tid and t.tname='张三' group by t.tname

-- 41、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
课程成绩去重后的课程数小于总课程数则不同课程存在相同成绩
select *,count(sc.score) count ,count(distinct sc.score) distinct_count from sc group by sc.sid

select * from (select *,count(sc.score) count ,count(distinct sc.score) distinct_count from sc group by sc.sid) t1 where distinct_count<count


-- 42、查询每门功成绩最好的前两名
select *,(select count(sc1.score) from sc sc1 where sc1.cid=sc.cid and sc1.score>sc.score)+1 rank from sc

select * from () t1 where rank<3

select * from (select *,(select count(sc1.score) from sc sc1 where sc1.cid=sc.cid and sc1.score>sc.score)+1 rank from sc) t1 where rank<3 order by t1.cid,t1.rank

-- ref 
select sc.* from sc sc where (select count(1) from sc sc1 where sc1.cid=sc.cid and sc1.score>sc.score)<2 order by sc.cid,sc.score;


-- 43、统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select sc.cid,count(sc.sid) count from sc group by sc.cid order by count desc,sc.cid

select * from ()t1 where t1.count>5
select * from (select sc.cid,count(sc.sid) count from sc group by sc.cid order by count desc,sc.cid)t1 where t1.count>5

-- ref 
SELECT cid,count(1) count FROM SC GROUP BY cid HAVING count>=5 ORDER BY count desc,cid ;
-- 44、检索至少选修两门课程的学生学号
select *,count(sc.cid) count from sc group by sc.sid

select * from () t1 where t1.count>=2

select * from (select *,count(sc.cid) count from sc group by sc.sid) t1 where t1.count>=2


-- ref 
SELECT a.*,b.count FROM Student a INNER JOIN (SELECT sid,count(cid) count  FROM SC GROUP BY sid HAVING count>1)b ON a.sid=b.sid GROUP BY 1,2,3,4;

-- 45、查询选修了全部课程的学生信息
select *,count(sc.cid) count from sc group by sc.sid having count=3

select *,count(sc.cid) count from sc group by sc.sid having count=(select count(c.cid) from course c)

-- 46、查询各学生的年龄
SELECT Student.*,YEAR(CURDATE())-YEAR(Student.sage) FROM Student;
SELECT Student.*,YEAR(current_date)-YEAR(Student.sage) FROM Student;

-- 47、查询本周过生日的学生
SELECT * FROM Student WHERE WEEKOFYEAR(NOW())-WEEKOFYEAR(sage)=0;
SELECT * FROM Student WHERE WEEKOFYEAR(current_date)-WEEKOFYEAR(sage)=0;

-- 48、查询下周过生日的学生
SELECT * FROM Student WHERE WEEKOFYEAR(current_date)-WEEKOFYEAR(sage)=-1;

-- 49、查询本月过生日的学生
select * from student where month(current_date)-month(sage)=0;

-- 50、查询下月过生日的学生
select * from student where month(current_date)-month(sage)=-1;

 

第二版

 


1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数
SELECT s.*,sc1.score ,sc2.score  
FROM student s,sc sc1,sc sc2
WHERE s.sid=sc1.sid AND s.sid=sc2.sid 
AND sc1.cid='01' AND sc2.cid='02'
AND sc1.score>sc2.score


SELECT * FROM student s 
LEFT JOIN sc sc1 ON s.sid=sc1.sid AND sc1.cid='01'
LEFT JOIN sc sc2 ON s.sid=sc2.sid AND sc2.cid='02'
WHERE IFNULL(sc1.score,0) > IFNULL(sc2.score,0)


2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数
3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
select sid,avg(sc.score) avg from sc  group by sc.sid having avg>=60
cast( avg(sc.score) as decimal(4,2))
select sid,cast( avg(sc.score) as decimal(4,2)) avg from sc  group by sc.sid having avg>=60

select s.sid,s.sname,a.avg from student s join () a on s.sid = a.sid

select s.sid,s.sname,a.avg from student s join (select sid,cast( avg(sc.score) as decimal(4,2)) avg from sc  group by sc.sid having avg>=60) a on s.sid = a.sid



4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩
5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩

select s.sid,s.sname,count(sc.cid),sum(sc.score) from student s join sc sc on s.sid=sc.sid group by s.sid ,s.sname


6、查询"李"姓老师的数量
select count(*) from teacher t where t.tname like "李%"

7、查询学过"张三"老师授课的同学的信息
select * from sc sc join course c on sc.cid=c.cid join teacher t on c.tid=t.tid and t.tname="张三"
8、查询没学过"张三"老师授课的同学的信息
select sc.sid sid from sc sc join course c on sc.cid=c.cid join teacher t on c.tid=t.tid and t.tname="张三"

select * from sc where sc.sid not in ()

select * from sc where sc.sid not in (select sc.sid sid from sc sc join course c on sc.cid=c.cid join teacher t on c.tid=t.tid and t.tname="张三")

9、查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息
方式一
并行:利用学生ID相等关联两张表 然后分别给不同的条件
select * from sc sc1,sc sc2 where sc1.sid = sc2.sid and sc1.cid="01" and sc2.cid="02"

select sc1.sid from sc sc1,sc sc2 where sc1.sid = sc2.sid and sc1.cid="01" and sc2.cid="02"

select * from student s where s.sid in ()

select * from student s where s.sid in (select sc1.sid from sc sc1,sc sc2 where sc1.sid = sc2.sid and sc1.cid="01" and sc2.cid="02")

方式二
串行:先查出学过01课程的学生 然后到这个结果集中查学过02课程的学生
select sid from sc where sc.cid ="01"

select * from sc sc,() a where sc.sid = a.sid and sc.cid="02" 

select * from sc sc,(select sid from sc where sc.cid ="01") a where sc.sid = a.sid and sc.cid="02" 
10、查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息

select sid from sc where sc.cid ="01"
select sid from sc where sc.cid ="02"

select sid from sc where sc.cid ="01" and sc.sid not in()

select sid from sc where sc.cid ="01" and sc.sid not in(select sid from sc s where s.cid ="02")

select sid from sc sc where sc.cid ="01" and not exists(select 1 from sc s where s.sid=sc.sid and s.cid ="02")



11、查询没有学全所有课程的同学的信息
在成绩表中查询课程总数小于总课程的同学
关联学生表 显示相关信息
select count(cid) from course
select sid from sc group by sc.sid having count(cid) <(select count(cid) from course) 

select sid from sc group by sc.sid having count(cid) <(select count(cid) from course) 

select * from student s where s.sid in ()
select * from student s where s.sid in (select sid from sc group by sc.sid having count(cid) <(select count(cid) from course))

select * from student s join () a on s.sid=a.sid
select * from student s join (select sid from sc group by sc.sid having count(*) <(select count(cid) from course)) a on s.sid=a.sid

select * from student s join sc sc where s.sid = sc.sid group by s.sid having count(sc.cid)<(select count(cid) c from course)


12、查询至少有一门课与学号为"01"的同学所学相同的同学的信息
思路
1查询01号学生所学课程ID
2在成绩表中查找课程ID与学号为"01"的同学所学相同的同学的信息

1查询01号学生所学课程ID
select cid from sc where sid='01'
2在成绩表中查找课程ID至少有一门课与学号为"01"的同学所学相同的同学的信息


select b.sid from sc b where cid in (select a.cid from sc a where a.sid='01') group by b.sid

select * from student s join () c where s.sid=c.sid 

select * from student s join (select b.sid sid from sc b where b.cid in (select a.cid from sc a where a.sid='01') group by b.sid) c on s.sid=c.sid 



13、查询和"01"号的同学学习的课程完全相同的其他同学的信息
思路
1查询01号学生所学课程ID
2在成绩表中查找课程ID与学号为"01"的同学所学相同的同学的信息

1查询01号学生所学课程ID
select cid from sc where sid='01'
2查询01号学生所学课程总数

select count(cid) from sc where sid='01'
3课程完全相同即课程在01号学生所学课程范围内 并且在数目一样

select * from sc a where a.cid in ()  group by a.sid having count(a.cid)=()

select * from sc a where a.cid in (select cid from sc where sid='01')  group by a.sid having count(a.cid)=(select count(cid) from sc where sid='01')


14、查询没学过"张三"老师讲授的任一门课程的学生姓名
查询学过张三老师课程的学生ID
select sc.sid from sc sc,course c ,teacher t where sc.cid = c.cid and c.tid = t.tid and t.tname ='张三'
查询没学过张三老师课程的学生
select s.* from student s where s.sid not in ()

select s.* from student s where s.sid not in (select sc.sid from sc sc,course c ,teacher t where sc.cid = c.cid and c.tid = t.tid and t.tname ='张三')

15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
查询两门及其以上不及格课程的同学
查询满足上不条件的学生学号,姓名及其平均成绩

查询两门及其以上不及格课程的同学
select *,count(sid) count from sc sc where sc.score<60 group by sc.sid having count >= 2

select sid from sc sc where sc.score<60 group by sc.sid having count(sid)  >= 2

查询满足上不条件的学生学号,姓名及其平均成绩
select sc.sid,avg(sc.score) from student s,sc sc where s.sid =sc.sid and sc.sid in () group by sc.sid 

select s.sname,sc.sid,avg(sc.score) avg from student s,sc sc where s.sid =sc.sid and sc.sid in (select sid from sc sc where sc.score<'60' group by sc.sid having count(sid)  >= 2) group by sc.sid



16、检索"01"课程分数小于60,按分数降序排列的学生信息
检索"01"课程分数小于60的学生
显示相关学生信息

检索"01"课程分数小于60的学生
select *  from sc s where s.cid ='01' and s.score < 60 order by s.score desc
显示相关学生信息
select * from student a join () b on a.sid = b.sid order by b.score desc

select a.sid sid,a.sname name,b.score score from student a join (select s.sid sid,s.score score from sc s where s.cid ='01' and s.score < 60) b on a.sid = b.sid order by score desc 


17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
select * from sc s join course c on s.cid = c.cid
列转行 语文 数学 英语

select s.sid sid ,
max(case when c.cname='语文' then s.score else null end) `语文`,
max(case when c.cname='数学' then s.score else null end) `数学`,
max(case when c.cname='英语' then s.score else null end) `英语`,
cast(avg(s.score) as decimal(4,2)) `平均成绩`
from sc s join course c on s.cid = c.cid group by s.sid

select s.sid sid ,
max(case when c.cname='语文' then s.score else null end) `语文`,
max(case when c.cname='数学' then s.score else null end) `数学`,
max(case when c.cname='英语' then s.score else null end) `英语`,
bround(avg(s.score),2) `平均成绩`
from sc s join course c on s.cid = c.cid group by s.sid



18、查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
select * from sc s join course c on s.cid=c.cid group by s.cid

select c.cid cid,c.cname name,
max(s.score) max,
min(s.score) min,
avg(s.score) avg, 
sum(case when s.score>=60 then 1 else 0 end)/count(1) `及格率`,
sum(case when s.score>=70 and s.score<80 then 1 else 0 end)/count(1) `中等率`,
sum(case when s.score>=80 and s.score<90 then 1 else 0 end)/count(1) `优良率`,
sum(case when s.score>=90 then 1 else 0 end)/count(1) `优秀率`
from sc s join course c on s.cid=c.cid group by c.cid,c.cname

select c.cid cid,c.cname name,
max(s.score) max,
min(s.score) min,
avg(s.score) avg, 
cast(sum(case when s.score>=60 then 1 else 0 end)/count(1) as decimal(4,2)) `及格率`,
cast(sum(case when s.score>=70 and s.score<80 then 1 else 0 end)/count(1)*100 as decimal(4,2)) `中等率`,
cast(sum(case when s.score>=80 and s.score<90 then 1 else 0 end)/count(1)*100 as decimal(4,2)) `优良率`,
cast(sum(case when s.score>=90 then 1 else 0 end)/count(1)*100 as decimal(4,2)) `优秀率`
from sc s join course c on s.cid=c.cid group by c.cid,c.cname



19、按各科成绩进行排序,并显示排名
select c.cid id,c.cname name,s.score score,() rank from sc s join course c on s.cid=c.cid 

select c.cid id,c.cname name,s.score score,
(select count(a.score) from sc a where a.cid=s.cid and s.score<a.score)+1 rank 
from sc s join course c on s.cid=c.cid order by c.cid,c.cname,rank

20、查询学生的总成绩并进行排名
计算总成绩
排名

计算总成绩
select sc.sid sid,sum(sc.score) tatal_score from sc sc group by sc.sid

排名

select *,(select count() from () a where b.tatal_score < a.tatal_score)+1 rank from () b 

select *,
(select count(a.tatal_score) 
from (select sc.sid sid,sum(sc.score) tatal_score from sc sc group by sc.sid) a 
where b.tatal_score < a.tatal_score)+1 rank 
from (select sc.sid sid,sum(sc.score) tatal_score from sc sc group by sc.sid) b 
order by rank

21、查询不同老师所教不同课程平均分从高到低显示

select c.tname tname,b.cname cname,avg(a.score) avg
from sc a join course b on a.cid=b.cid join teacher c on b.tid = c.tid 
group by c.tname,b.cname

select c.tname tname,b.cname cname,cast(avg(a.score) as decimal(4,2)) avg
from sc a join course b on a.cid=b.cid join teacher c on b.tid = c.tid 
group by c.tname,b.cname

22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
select *,() rank from sc a

select *,(select count(distinct b.score) from sc b where a.cid=b.cid and b.score>a.score)+1 rank from sc a
order by a.cid,rank

select * from () t where t.tank >=2 and t.tank <=3

select * from (select *,(select count(distinct b.score) from sc b where a.cid=b.cid and b.score>a.score)+1 rank from sc a
) t where t.rank >=2 and t.rank <=3 order by cid,rank

23、统计各科成绩各分数段人数:课程编号,课程名称, 100-85 , 85-70 , 70-60 , 0-60 及所占百分比
横向
select s.cid,c.cname,
  sum(case when s.score<=100 and s.score >85 then 1 else 0 end) `100-85`,
  sum(case when s.score<=85 and s.score >70 then 1 else 0 end) `85-70`,
  sum(case when s.score<=70 and s.score >60 then 1 else 0 end) `70-60`,
  sum(case when s.score<=60 and s.score >=0 then 1 else 0 end) `60-0`
from
sc s join course c on s.cid = c.cid
group by s.cid,c.cname


select s.cid,c.cname,
  sum(case when s.score<=100 and s.score >85 then 1 else 0 end) `100-85`,
  sum(case when s.score<=100 and s.score >85 then 1 else 0 end)/sum(1) `百分比`,
  sum(case when s.score<=85 and s.score >70 then 1 else 0 end) `85-70`,
  sum(case when s.score<=85 and s.score >70 then 1 else 0 end)/sum(1) `百分比`,
  sum(case when s.score<=70 and s.score >60 then 1 else 0 end) `70-60`,
  sum(case when s.score<=70 and s.score >60 then 1 else 0 end)/sum(1) `百分比`,
  sum(case when s.score<=60 and s.score >=0 then 1 else 0 end) `60-0`,
  sum(case when s.score<=60 and s.score >=0 then 1 else 0 end)/sum(1) `百分比`
from
sc s join course c on s.cid = c.cid
group by s.cid,c.cname

纵向

select 
  s.cid,c.cname,
	(
	case 
	when s.score<=100 and s.score >85 then '100-85'
	when s.score<=85 and s.score >70 then '85-70'
	when s.score<=70 and s.score >60 then '70-60'
	when s.score<=60 and s.score >=0 then '60-0'
	end
	) `分段`,count(1) `人数`
from
sc s join course c on s.cid = c.cid
group by s.cid,c.cname,分段

select 
  s.cid,c.cname,
    (
    case 
    when s.score<=100 and s.score >85 then '100-85'
    when s.score<=85 and s.score >70 then '85-70'
    when s.score<=70 and s.score >60 then '70-60'
    when s.score<=60 and s.score >=0 then '60-0'
    end
    ) `分段`,count(1) `人数`
from
sc s join course c on s.cid = c.cid
group by s.cid,c.cname, 
(case 
    when s.score<=100 and s.score >85 then '100-85'
    when s.score<=85 and s.score >70 then '85-70'
    when s.score<=70 and s.score >60 then '70-60'
    when s.score<=60 and s.score >=0 then '60-0'
  end)

28、查询男生、女生人数
横向

select 
sum(case when ssex ='男' then 1 else 0 end) `男`,
sum(case when ssex ='女' then 1 else 0 end) `女`
from student s  
纵向

select
  (case when ssex='男' then '男' else '女' end) `性别`,count(1) `人数`
from 
  student
group by 
  (case when ssex = '男' then '男' else '女' end)
	

36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数;
-- 如果将任何一门成绩在70分以上,理解为所有成绩在70分以上的话
思路
1.查出每个学生的最小的成绩 => t1
2.选出最小的成绩比70大的学生,那么此学生的所有成绩都大于70 => t2
3.关联其它表,显示相关信息

1.查出每个学生的最小的成绩
select sid,min(score) min_score from sc group by sid

2.选出最小的成绩比70大的学生,那么此学生的所有成绩都大于70
select sid from () t1 where t1.min_score>70
select sid from (select sid,min(score) min_score from sc group by sid) t1 where t1.min_score>70

3.关联其它表,显示相关信息
select * from student s,sc sc,course c,() t2 where s.sid =sc.sid and sc.cid =c.cid and sc.sid = t2.sid

select 
    s.sname `学生姓名`,c.cname `课程名`,sc.score `分数` 
from 
    student s,sc sc,course c,(select sid from (select sid,min(score) min_score from sc group by sid) t1 where t1.min_score>70) t2 
where 
    s.sid =sc.sid and sc.cid =c.cid and sc.sid = t2.sid
	
	
	
-- 如果将任何一门成绩在70分以上,理解为其中一门成绩在70分以上的话
思路
1.查出每个学生的最大的成绩 => t1
2.选出最大的成绩比70大的学生,那么此学生其中一门成绩大于70 => t2
3.关联其它表,显示相关信息

1.查出每个学生的最大的成绩
select sid,max(score) max_score from sc group by sid

2.选出最大的成绩比70大的学生,那么此学生其中一门成绩大于70 => t2
select sid from () t1 where t1.max_score>70
select sid from (select sid,max(score) max_score from sc group by sid) t1 where t1.max_score>70

3.关联其它表,显示相关信息
select * from student s,sc sc,course c,() t2 where s.sid =sc.sid and sc.cid =c.cid and sc.sid = t2.sid

select 
    s.sname `学生姓名`,c.cname `课程名`,sc.score `分数` 
from 
    student s,sc sc,course c,(select sid from (select sid,max(score) max_score from sc group by sid) t1 where t1.max_score>70) t2 
where 
    s.sid =sc.sid and sc.cid =c.cid and sc.sid = t2.sid
	

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值