50道mysql练习题

student(sid,sname,sage,ssex) 学生表 
sc(sid,cid,score) 成绩表 
course(cid,cname,tid) 课程表 
teacher(tid,tname) 教师表

1、建表语句:

CREATE TABLE student 
  ( 
     sid    INT, 
     sname nvarchar(32), 
     sage  INT, 
     ssex  nvarchar(8) 
  ) 

CREATE TABLE course 
  ( 
     cid    INT, 
     cname nvarchar(32), 
     tid    INT 
  ) 

CREATE TABLE sc 
  ( 
     sid    INT, 
     cid    INT, 
     score  INT 
  ) 

CREATE TABLE teacher 
  ( 
     tid    INT, 
     tname nvarchar(16) 
  ) 

2、插入测试数据语句 :

 insert into student select 1,N'刘一',18,N'男' union all
 select 2,N'钱二',19,N'女' union all
 select 3,N'张三',17,N'男' union all
 select 4,N'李四',18,N'女' union all
 select 5,N'王五',17,N'男' union all
 select 6,N'赵六',19,N'女' 
 
 insert into teacher select 1,N'叶平' union all
 select 2,N'贺高' union all
 select 3,N'杨艳' union all
 select 4,N'周磊'
 
 insert into course select 1,N'语文',1 union all
 select 2,N'数学',2 union all
 select 3,N'英语',3 union all
 select 4,N'物理',4
 
 insert into sc 
 select 1,1,56 union all 
 select 1,2,78 union all 
 select 1,3,67 union all 
 select 1,4,58 union all 
 select 2,1,79 union all 
 select 2,2,81 union all 
 select 2,3,92 union all 
 select 2,4,68 union all 
 select 3,1,91 union all 
 select 3,2,47 union all 
 select 3,3,88 union all 
 select 3,4,56 union all 
 select 4,2,88 union all 
 select 4,3,90 union all 
 select 4,4,93 union all 
 select 5,1,46 union all 
 select 5,3,78 union all 
 select 5,4,53 union all 
 select 6,1,35 union all 
 select 6,2,68 union all 
 select 6,4,71

3、解法并非一种,答案仅供参考!

#1、查询“001”课程比“002”课程成绩高的所有学生的学号; 
select a.sid from (select sid,score from sc where cid='001') a,(select sid,score from sc where cid='002') b
where a.score>b.score and a.sid=b.sid;

#2、查询平均成绩大于60分的同学的学号和平均成绩;
select sid,avg(score) as '平均分' 
from sc 
group by sid having avg(score)>60;
 
#3、查询所有同学的学号、姓名、选课数、总成绩; 
select student.sid,sname,count(cid) as '选课数',sum(score) as '总成绩'
from student LEFT JOIN sc
ON student.sid=sc.sid
GROUP BY student.sid,sname;

#4、查询姓“周”的老师的个数;
select count(tname) from teacher where tname like '周%';

#5、查询没学过“叶平”老师课的同学的学号、姓名;
select sid,sname 
from student 
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 = '叶平'
);

#6、查询学过“001”并且也学过编号“002”课程的同学的学号、姓名;
-- 方法一:求交集inner join,分别查001和002的再取相同部分
select a.sid,a.sname from
(select student.sid,student.sname from student,sc where student.sid=sc.sid and sc.cid='001') a
INNER  JOIN
(select student.sid,student.sname from student,sc where student.sid=sc.sid and sc.cid='002') b
on a.sid=b.sid;

-- 方法二:使用exists 
select student.sid,sname 
from student,sc 
where student.sid=sc.sid and sc.cid='001' 
and exists 
(
	select * from sc as sc2 where sc2.sid=sc.sid and sc2.cid='002'
); 

#7、查询学过“叶平”老师所教的所有课的同学的学号、姓名;
select sid,sname 
from student where sid in 
(
	select sid 
	from sc ,course ,teacher 
	where sc.cid=course.cid and teacher.tid=course.tid and teacher.tname='叶平' 
	group by sid 
	having count(sc.cid)=
	(
		select count(cid) from course,teacher where teacher.tid=course.tid and tname='叶平'
	)
); 

#8、查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名;
select student.sid,sname from student WHERE sid in (
	select a.sid from (select sid,score from sc where sc.cid='002')a,(select sid,score from sc where sc.cid='001')b
	where a.scoresid,sname,score(条件是cid='001'的成绩),score2(作为子查询查002课程的成绩)
select sid,sname from (
	select student.sid,student.sname,score ,(select score from sc sc_2 where sc_2.sid=student.sid and sc_2.cid='002') score2 
	from student,sc 
	where student.sid=sc.sid and cid='001') newTable where score2 60);

#10、查询没有学全所有课的同学的学号、姓名; 
-- (思路:按sid,sname分组查出所有有课程的学生,然后having过滤出课程数少于课程表课程数的学生)
select student.sid,student.sname 
from student,sc
where student.sid=sc.sid 
group by  student.sid,student.sname 
having count(cid) <(select count(cid) from course); 

#11、查询至少有一门课与学号为“001”的同学所学相同的同学的学号和姓名;
select distinct student.sid,sname 
from student,sc 
where student.sid=sc.sid and cid in (select cid from sc where sid='001');

#12、查询至少学过学号为“001”同学所有一门课的其他同学学号和姓名; (和上题目不同在于其他)
select distinct student.sid,sname 
from student,sc 
where student.sid=sc.sid and student.sid<>'001' and cid in (select cid from sc where sid='001');

#13、把“sc”表中“叶平”老师教的课的成绩都更改为此课程的平均成绩; 
-- update sc set score=
-- (
-- 	select avg(score) as avgScore
--  from sc,course,teacher 
-- 	where sc.cid=course.cid and course.tid=teacher.tid and teacher.tname='叶平'
-- )
-- where cid in 
-- (
-- 	select distinct(sc.cid) as sc_cid from sc,course,teacher
--  where sc.cid=course.cid and course.tid=teacher.tid and teacher.tname='叶平'
-- )
#报错:[Err] 1093 - You can't specify target table 'sc' for update in FROM clause
#原因:在mysql中,不能先select一个表的记录,在按此条件进行更新和删除同一个表的记录。
-- 解决办法是,将select得到的结果,再通过中间表select一遍,这样就规避了错误,
-- 这个问题只出现于mysql,mssql和oracle不会出现此问题。
-- 正解如下:思路:通过中间表a,b来更新记录
update sc set score=
(
    select a.avgScore from
  (select avg(score) as avgScore
		from sc,course,teacher 
		where sc.cid=course.cid and course.tid=teacher.tid and teacher.tname='叶平') a
)
where cid in 
(
	select b.sc_cid from 
  (select distinct(sc.cid) as sc_cid from sc,course,teacher
  where sc.cid=course.cid and course.tid=teacher.tid and teacher.tname='叶平') b
)

#14、查询和“002”号的同学学习的课程完全相同的其他同学学号和姓名:
-- 思路:1、cid in (select cid from sc where sc.sid='002'),2、并且count(*)=(select count(*) from sc where sc.sid='002')数量一样。就能找到完全相同的了
select student.sid,sname
from student,sc 
where cid in(select cid from sc where sc.sid='002') and sc.sid=student.sid and student.sid<>'002'
group by student.sid,sname
having count(*)=(select count(*) from sc where sc.sid='002');
-- 或者
select student.sid,sname 
from student
where student.sid!='002' and student.sid in 
(
    select distinct(sid) from sc
    where cid in (select cid from sc where sid='002')
    group by sid
    having COUNT(distinct cid)=
    (
        select COUNT(distinct cid) from sc where sid='002'
    )
);

#15、删除学习“叶平”老师课的SC表记录
delete from sc where cid in
(
    select c.cid from course c,teacher t
    where c.tid=t.tid and t.tname='叶平'
);

#16、向SC表中插入一些记录,这些记录要求符合以下条件:①没有上过编号“002”课程的同学学号;②插入“002”号课程的平均成绩; 
-- 分为两部分insert into sc 和另外的部分
insert into sc 
select sid,'002',(select AVG(score) from sc where cid='002') 
from student 
where student.sid not in (select distinct(sid) from sc where cid='002');

#17、按平均成绩从低到高显示所有学生的“语文”、“数学”、“英语”三门的课程成绩,
-- 按如下形式显示: 学生ID,语文,数学,英语,有效课程数,有效平均分;
select t.sid as '学生ID',
(select score from sc where sid=t.sid and cid='001') as '语文',
(select score from sc where sid=t.sid and cid='002') as '数学',
(select score from sc where sid=t.sid and cid='003') as '英语',
COUNT(t.cid) as '有效课程数',
AVG(t.score) as '有效平均分'
from sc t
group by t.sid
order by AVG(t.score);

#18、查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分 
select cid as '课程ID',MAX(score) as '最高分',MIN(score) as '最低分' 
from sc
group by cid;

#19、按各科平均成绩从低到高和及格率的百分数从高到低顺序 
select sc.cid,course.cname,IFNULL(AVG(sc.score),0) as 'AvgScore',
100 * SUM(CASE WHEN  IFNULL(sc.score,0)>=60 THEN 1 ELSE 0 END)/COUNT(*) as 'Percent(%)'
from sc,course
where sc.cid=course.cid
group by sc.cid,course.cname  
order by 100 * SUM(CASE WHEN  IFNULL(sc.score,0)>=60 THEN 1 ELSE 0 END)/COUNT(*) desc

#20、查询如下课程平均成绩和及格率的百分数(用"1行"显示): 语文(001),数学(002),
-- 英语 (003),物理(004) 
select 
ROUND(SUM(CASE WHEN cid='001' THEN score ELSE 0 END)/SUM(CASE cid WHEN '001' THEN 1 ELSE 0 END),2) as '语文平均分',
CONCAT( ROUND( 100 * SUM(CASE WHEN cid='001' and score>=60 THEN 1 ELSE 0 END)/SUM(CASE cid WHEN '001' THEN 1 ELSE 0 END), 2 ), '', '%' ) as '语文及格百分比',
ROUND(SUM(CASE WHEN cid='002' THEN score ELSE 0 END)/SUM(CASE cid WHEN '002' THEN 1 ELSE 0 END),2) as '数学平均分',
CONCAT( ROUND( 100 * SUM(CASE WHEN cid='002' and score>=60 THEN 1 ELSE 0 END)/SUM(CASE cid WHEN '002' THEN 1 ELSE 0 END), 2 ), '', '%' ) as '数学及格百分比',
ROUND(SUM(CASE WHEN cid='003' THEN score ELSE 0 END)/SUM(CASE cid WHEN '003' THEN 1 ELSE 0 END),2) as '英语平均分',
CONCAT( ROUND( 100 * SUM(CASE WHEN cid='003' and score>=60 THEN 1 ELSE 0 END)/SUM(CASE cid WHEN '003' THEN 1 ELSE 0 END), 2 ), '', '%' ) as '英语及格百分比',
ROUND(SUM(CASE WHEN cid='004' THEN score ELSE 0 END)/SUM(CASE cid WHEN '004' THEN 1 ELSE 0 END),2) as '物理平均分',
CONCAT( ROUND( 100 * SUM(CASE WHEN cid='004' and score>=60 THEN 1 ELSE 0 END)/SUM(CASE cid WHEN '004' THEN 1 ELSE 0 END), 2 ), '', '%' ) as '物理及格百分比'
from sc

-- CONCAT( ROUND( vcr.number_vote / ct.number_vote * 100, 2 ), '', '%' )
-- select concat(round(值A/值B*100,m),'%')计算百分比,其中round函数返回数字表达式并四舍五入为指定的长度或精度。

#21、查询不同老师所教不同课程平均分从高到低显示
select c.cid,MAX(c.cname) as 'cname',MAX(t.tid) as 'tid',MAX(t.tname) as 'tname',AVG(score) as 'AvgScore' 
from teacher t,course c,sc
where sc.cid=c.cid and c.tid=t.tid
group by  c.cid
order by AvgScore descm 9+
-- 21题用到MAX(列名):因为使用group by时,select 涉及的列要么是分组的依据(本例:cid),要么包含在聚合函数(如本例:score)中。
--  所以像cname,tid,tname也应该包含在聚合函数中,这里用MAX()

#22、查询如下课程成绩第 3 名到第 6 名的学生成绩单:语文(001),数学(002),英语(003),物理(004) 
-- 按如下形式显示:[学生ID],[学生姓名],语文,数学,英语,物理,平均成绩 
-- 这题好像不是这样的...
select student.sid as '学生ID',student.sname as '学生名称',
    max(case cid when '001' then score end) as '语文',
    max(case cid when '002' then score end) as '数学',
    max(case cid when '003' then score end) as '英语',
    max(case cid when '004' then score end) as '物理',
    avg(score) as '平均成绩'
from student inner join sc on student.sid=sc.sid
and sc.sid in (
    select sid
    from sc t1
    where (select count(*) from sc where sc.cid=t1.cid and sc.score >=t1.score ) between 3 and 6 and t1.cid in (001,002,003,004)
		
)
group by student.sid,sname;

#23、统计列印各科成绩,各分数段人数:课程ID,课程名称,[100-85],[84-70],[69-60],[ <60] 
select sc.cid as '课程ID',MAX(course.cname) as '课程名称',
SUM(CASE WHEN sc.Score BETWEEN 85 and 100 THEN 1 ELSE 0 END) as '[85-100]',
SUM(CASE WHEN sc.Score BETWEEN 70 and 84 THEN 1 ELSE 0 END) as '[70-84]',
SUM(CASE WHEN sc.Score BETWEEN 60 and 69 THEN 1 ELSE 0 END) as '[60-69]',
SUM(CASE WHEN sc.Score BETWEEN 0 and 60 THEN 1 ELSE 0 END) as '[<60]'
from sc,course
where sc.cid=course.cid
group by sc.cid

#24、查询学生平均成绩及其名次 
select s.sid,s.sname,T2.AvgScore,
(
	select COUNT(AvgScore) 
	from (select sid,AVG(Score) as 'AvgScore' from sc group by sid) as T1 
	where T2.AvgScore1;

#31、查询1981年出生的学生名单(注:Student表中Sage列的类型是datetime) ;
-- 题目很迷,不是很懂
select Sname, CONVERT(char (11),DATEPART(year,sage)) as age 
from student 
where  CONVERT(char(11),DATEPART(year,sage))='1981'; 

#32、查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列;
select sc.cid,cname,AVG(score) 
from sc,course 
where sc.cid=course.cid 
group by sc.cid,cname 
order by AVG(score),cid desc;

#33、查询平均成绩大于85的所有学生的学号、姓名和平均成绩;
select student.sid,sname,AVG(score) 
from student,sc 
where student.sid=sc.sid 
group by student.sid,sname 
having AVG(score)>85;

#34、查询课程名称为“数学”,且分数低于60的学生姓名和分数;
select sname,score 
from student,sc,course 
where student.sid=sc.sid and sc.cid=course.cid and course.cname='数学' and score<60
#35、查询所有学生的选课情况;
select student.sid,sname,course.cid,cname from student,sc,course
where student.sid=sc.sid and sc.cid=course.cid
order by course.cid,student.sid;

#36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数; 
select sname,cname,score 
from student,sc,course 
where student.sid=sc.sid and sc.cid=course.cid and score>70;

#37、查询有不及格的课程,并按课程号从大到小排列;
select distinct sc.cid,c.cname from sc,course c
where sc.cid=c.cid and sc.score<60
order by sc.cid desc

#38、查询课程编号为003且课程成绩在80分以上的学生的学号和姓名; 
select s.sid,sname 
from student s,sc
where s.sid=sc.sid and sc.cid='003' and score>=80;

#39、求选了课程的学生人数;
select count(*) from sc;

#40、查询选修“杨艳”老师所授课程的学生中,成绩最高的学生姓名及其成绩;
select s.sname,sc.score 
from student s,sc,course c,teacher t
where s.sid=sc.sid and sc.cid=c.cid and c.tid=t.tid and t.tname='杨艳' and sc.score=
(
	select max(sc_2.score)from sc sc_2 where sc.cid=sc_2.cid 
); 

#41、查询各个课程及相应的选修人数;
select sc.cid,c.cname,COUNT(distinct sid) as 'StuCount' from sc,course c
where sc.cid=c.cid
group by sc.cid,c.cname

#42、查询不同课程但成绩相同的学生的学号、课程号、学生成绩;
select distinct sc1.sid,sc1.cid,sc1.score from sc sc1,sc sc2
where sc1.cid!=sc2.cid and sc1.score=sc2.score
order by sc1.score asc

#43、查询每门课程成绩最好的前两名;(和25题有点重复了)
select student.sid,sname,k.cid,cname,score from student,course,
(
	SELECT sid,cid,score
	FROM sc
	WHERE EXISTS
	(
		SELECT COUNT(*)
		FROM sc sc2
		WHERE sc.cid=sc2.cid AND sc.score=10
order by StuCount desc,sc.cid asc

#45、检索至少选修两门课程的学生学号;
select distinct sc.sid from sc
group by sc.sid
having COUNT(sc.cid)>=2

#46、查询全部学生都选修的课程的课程号和课程名;
select sc.cid,c.cname from sc,course c
where sc.cid=c.cid
group by sc.cid,c.cname 
having COUNT(sc.sid)=(select COUNT(distinct s.sid) from student s);
-- 思路:统计学生表学生数a,在sc表中如果哪门课程对应的学生数=a条记录就说明全选了

#47、查询没学过“叶平”老师讲授的任一门课程的学生姓名;
select s.sid,s.sname from student s where s.sid not in 
(
	select sc.sid from sc,course c,teacher t where
	sc.cid=c.cid and c.tid=t.tid and t.tname='叶平'
);


#48、查询两门以上不及格课程的同学的学号及其平均成绩;
select sc.sid,AVG(IFNULL(sc.score,0)) from sc where sc.sid in 
(
	select sc_2.sid 
	from sc sc_2 
	where sc_2.score<60 
	group by sc_2.sid 
	having COUNT(sc_2.cid)>=2
)
group by sc.sid;

#49、检索“004”课程分数小于60,按分数降序排列的同学学号;
select sid from sc where cid='004'and score <60 order by score desc; 

#50、删除“002”同学的“001”课程的成绩;
delete from sc where sid='002' and cid='001';

 

你可能感兴趣的:(mysql)