数据库大型应用——笔记2 50道mysql练习题

news/发布时间2024/5/10 0:06:59

  复健了一下mysql,练习内容是mysql50题目。(算法也有在写啦,前几天还被数论折磨)

 一.开始前数据库中的表的各种信息

   1.1表名与字段

      –1.学生表
      Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别
      –2.课程表
      Course(c_id,c_name,t_id) – –课程编号, 课程名称, 教师编号
      –3.教师表
      Teacher(t_id,t_name) –教师编号,教师姓名
      –4.成绩表
      Score(s_id,c_id,s_score) –学生编号,课程编号,分数

   1.2测试数据

--建表
--学生表
CREATE TABLE `Student`(
`s_id` VARCHAR(20),
`s_name` VARCHAR(20) NOT NULL DEFAULT '',
`s_birth` VARCHAR(20) NOT NULL DEFAULT '',
`s_sex` VARCHAR(10) NOT NULL DEFAULT '',
PRIMARY KEY(`s_id`)
);
--课程表
CREATE TABLE `Course`(
`c_id` VARCHAR(20),
`c_name` VARCHAR(20) NOT NULL DEFAULT '',
`t_id` VARCHAR(20) NOT NULL,
PRIMARY KEY(`c_id`)
);
--教师表
CREATE TABLE `Teacher`(
`t_id` VARCHAR(20),
`t_name` VARCHAR(20) NOT NULL DEFAULT '',
PRIMARY KEY(`t_id`)
);
--成绩表
CREATE TABLE `Score`(
`s_id` VARCHAR(20),
`c_id` VARCHAR(20),
`s_score` INT(3),
PRIMARY KEY(`s_id`,`c_id`)
);
--插入学生表测试数据
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' , '');
--课程表测试数据
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');--教师表测试数据
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');--成绩表测试数据
insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);

 二.练习题和sql

ps:这些是我从网上搜寻来的答案,建议直接去作者博客:Mysql Sql 语句练习题 (50道) - 梅花GG - 博客园 (cnblogs.com)   

-- 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数 
select st.*,sc.s_score as '语文' ,sc2.s_score '数学' 
from student st
left join score sc on sc.s_id=st.s_id and sc.c_id='01' 
left join score sc2 on sc2.s_id=st.s_id and sc2.c_id='02'  
where sc.s_score>sc2.s_score-- 2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数
select st.*,sc.s_score '语文',sc2.s_score '数学' from student st
left join score sc on sc.s_id=st.s_id and sc.c_id='01'
left join score sc2 on sc2.s_id=st.s_id and sc2.c_id='02'
where sc.s_score<sc2.s_score-- 3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
select st.s_id,st.s_name,ROUND(AVG(sc.s_score),2) cjScore from student st
left join score sc on sc.s_id=st.s_id
group by st.s_id having AVG(sc.s_score)>=60-- 4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩-- (包括有成绩的和无成绩的)
select st.s_id,st.s_name,(case when ROUND(AVG(sc.s_score),2) is null then 0 else ROUND(AVG(sc.s_score)) end ) cjScore from student st
left join score sc on sc.s_id=st.s_id
group by st.s_id having AVG(sc.s_score)<60 or AVG(sc.s_score) is NULL-- 5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
select st.s_id,st.s_name,count(c.c_id),( case when SUM(sc.s_score) is null or sum(sc.s_score)="" then 0 else SUM(sc.s_score) end) from student st
left join score sc on sc.s_id =st.s_id 
left join course c on c.c_id=sc.c_id
group by st.s_id-- 6、查询"李"姓老师的数量 
select t.t_name,count(t.t_id) from teacher t
group by t.t_id having t.t_name like "李%"; -- 7、查询学过"张三"老师授课的同学的信息 
select st.* from student st 
left join score sc on sc.s_id=st.s_id
left join course c on c.c_id=sc.c_id
left join teacher t on t.t_id=c.t_idwhere t.t_name="张三"-- 8、查询没学过"张三"老师授课的同学的信息 -- 张三老师教的课select c.* from course c left join teacher t on t.t_id=c.t_id where  t.t_name="张三"-- 有张三老师课成绩的st.s_idselect sc.s_id from score sc where sc.c_id in (select c.c_id from course c left join teacher t on t.t_id=c.t_id where  t.t_name="张三")-- 不在上面查到的st.s_id的学生信息,即没学过张三老师授课的同学信息select st.* from student st where st.s_id not in(select sc.s_id from score sc where sc.c_id in (select c.c_id from course c left join teacher t on t.t_id=c.t_id where  t.t_name="张三"))-- 9、查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息
select st.* from student st 
inner join score sc on sc.s_id = st.s_id
inner join course c on c.c_id=sc.c_id and c.c_id="01"
where st.s_id in (
select st2.s_id from student st2 
inner join score sc2 on sc2.s_id = st2.s_id
inner join course c2 on c2.c_id=sc2.c_id and c2.c_id="02"
)网友提供的思路(厉害呦~):
SELECT st.*
FROM student st
INNER JOIN score sc ON sc.`s_id`=st.`s_id`
GROUP BY st.`s_id`
HAVING SUM(IF(sc.`c_id`="01" OR sc.`c_id`="02" ,1,0))>1-- 10、查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息
select st.* from student st 
inner join score sc on sc.s_id = st.s_id
inner join course c on c.c_id=sc.c_id and c.c_id="01"
where st.s_id not in (
select st2.s_id from student st2 
inner join score sc2 on sc2.s_id = st2.s_id
inner join course c2 on c2.c_id=sc2.c_id and c2.c_id="02"
)-- 11、查询没有学全所有课程的同学的信息-- 太复杂,下次换一种思路,看有没有简单点方法-- 此处思路为查学全所有课程的学生id,再内联取反面
select * from student where s_id not in (
select st.s_id from student st 
inner join score sc on sc.s_id = st.s_id and sc.c_id="01"
where st.s_id  in (
select st2.s_id from student st2 
inner join score sc2 on sc2.s_id = st2.s_id and sc2.c_id="02"
) and st.s_id in (
select st2.s_id from student st2 
inner join score sc2 on sc2.s_id = st2.s_id and sc2.c_id="03"
))
-- 来自一楼网友的思路,左连接,根据学生id分组过滤掉 数量小于 课程表中总课程数量的结果(show me his code),简洁不少。
select st.* from Student st
left join Score S
on st.s_id = S.s_id
group by st.s_id
having count(c_id)<(select count(c_id) from Course)-- 12、查询至少有一门课与学号为"01"的同学所学相同的同学的信息
select distinct st.* from student st 
left join score sc on sc.s_id=st.s_id
where sc.c_id in (
select sc2.c_id from student st2
left join score sc2 on sc2.s_id=st2.s_id
where st2.s_id ='01'
)-- 13、查询和"01"号的同学学习的课程完全相同的其他同学的信息
select  st.* from student st 
left join score sc on sc.s_id=st.s_id
group by st.s_id
having group_concat(sc.c_id) = 
(
select  group_concat(sc2.c_id) from student st2
left join score sc2 on sc2.s_id=st2.s_id
where st2.s_id ='01'
)-- 14、查询没学过"张三"老师讲授的任一门课程的学生姓名
select st.s_name from student st 
where st.s_id not in (
select sc.s_id from score sc 
inner join course c on c.c_id=sc.c_id
inner join teacher t on t.t_id=c.t_id and t.t_name="张三"
)-- 15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
select st.s_id,st.s_name,avg(sc.s_score) from student st
left join score sc on sc.s_id=st.s_id
where sc.s_id in (
select sc.s_id from score sc 
where sc.s_score<60 or sc.s_score is NULL
group by sc.s_id having COUNT(sc.s_id)>=2
)
group by st.s_id-- 16、检索"01"课程分数小于60,按分数降序排列的学生信息
select st.*,sc.s_score from student st 
inner join score sc on sc.s_id=st.s_id and sc.c_id="01" and sc.s_score<60
order by sc.s_score desc-- 17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩-- 可加round,case when then else end 使显示更完美
select st.s_id,st.s_name,avg(sc4.s_score) "平均分",sc.s_score "语文",sc2.s_score "数学",sc3.s_score "英语" from student st
left join score sc  on sc.s_id=st.s_id  and sc.c_id="01"
left join score sc2 on sc2.s_id=st.s_id and sc2.c_id="02"
left join score sc3 on sc3.s_id=st.s_id and sc3.c_id="03"
left join score sc4 on sc4.s_id=st.s_id
group by st.s_id 
order by SUM(sc4.s_score) desc-- 18.查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
-- 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
select c.c_id,c.c_name,max(sc.s_score) "最高分",MIN(sc2.s_score) "最低分",avg(sc3.s_score) "平均分" 
,((select count(s_id) from score where s_score>=60 and c_id=c.c_id )/(select count(s_id) from score where c_id=c.c_id)) "及格率"
,((select count(s_id) from score where s_score>=70 and s_score<80 and c_id=c.c_id )/(select count(s_id) from score where c_id=c.c_id)) "中等率"
,((select count(s_id) from score where s_score>=80 and s_score<90 and c_id=c.c_id )/(select count(s_id) from score where c_id=c.c_id)) "优良率"
,((select count(s_id) from score where s_score>=90 and c_id=c.c_id )/(select count(s_id) from score where c_id=c.c_id)) "优秀率"
from course c
left join score sc on sc.c_id=c.c_id 
left join score sc2 on sc2.c_id=c.c_id 
left join score sc3 on sc3.c_id=c.c_id 
group by c.c_id-- 19、按各科成绩进行排序,并显示排名(实现不完全)
-- mysql没有rank函数
-- 加@score是为了防止用union all 后打乱了顺序
select c1.s_id,c1.c_id,c1.c_name,@score:=c1.s_score,@i:=@i+1 from (select c.c_name,sc.* from course c 
left join score sc on sc.c_id=c.c_id
where c.c_id="01" order by sc.s_score desc) c1 ,
(select @i:=0) a
union all 
select c2.s_id,c2.c_id,c2.c_name,c2.s_score,@ii:=@ii+1 from (select c.c_name,sc.* from course c 
left join score sc on sc.c_id=c.c_id
where c.c_id="02" order by sc.s_score desc) c2 ,
(select @ii:=0) aa 
union all
select c3.s_id,c3.c_id,c3.c_name,c3.s_score,@iii:=@iii+1 from (select c.c_name,sc.* from course c 
left join score sc on sc.c_id=c.c_id
where c.c_id="03" order by sc.s_score desc) c3;
set @iii=0;-- 20、查询学生的总成绩并进行排名
select st.s_id,st.s_name
,(case when sum(sc.s_score) is null then 0 else sum(sc.s_score) end)from student st
left join score sc on sc.s_id=st.s_id
group by st.s_id order by sum(sc.s_score) desc-- 21、查询不同老师所教不同课程平均分从高到低显示 
select t.t_id,t.t_name,c.c_name,avg(sc.s_score) from teacher t 
left join course c on c.t_id=t.t_id 
left join score sc on sc.c_id =c.c_id
group by t.t_id
order by avg(sc.s_score) desc-- 22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
select a.* from (
select st.*,c.c_id,c.c_name,sc.s_score from student st
left join score sc on sc.s_id=st.s_id
inner join course c on c.c_id =sc.c_id and c.c_id="01"
order by sc.s_score desc LIMIT 1,2 ) a
union all
select b.* from (
select st.*,c.c_id,c.c_name,sc.s_score from student st
left join score sc on sc.s_id=st.s_id
inner join course c on c.c_id =sc.c_id and c.c_id="02"
order by sc.s_score desc LIMIT 1,2) b
union all
select c.* from (
select st.*,c.c_id,c.c_name,sc.s_score from student st
left join score sc on sc.s_id=st.s_id
inner join course c on c.c_id =sc.c_id and c.c_id="03"
order by sc.s_score desc LIMIT 1,2) c-- 23、统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比
select c.c_id,c.c_name 
,((select count(1) from score sc where sc.c_id=c.c_id and sc.s_score<=100 and sc.s_score>80)/(select count(1) from score sc where sc.c_id=c.c_id )) "100-85"
,((select count(1) from score sc where sc.c_id=c.c_id and sc.s_score<=85 and sc.s_score>70)/(select count(1) from score sc where sc.c_id=c.c_id )) "85-70"
,((select count(1) from score sc where sc.c_id=c.c_id and sc.s_score<=70 and sc.s_score>60)/(select count(1) from score sc where sc.c_id=c.c_id )) "70-60"
,((select count(1) from score sc where sc.c_id=c.c_id and sc.s_score<=60 and sc.s_score>=0)/(select count(1) from score sc where sc.c_id=c.c_id )) "60-0"
from course c order by c.c_id-- 24、查询学生平均成绩及其名次 
set @i=0;
select a.*,@i:=@i+1 from (
select st.s_id,st.s_name,round((case when avg(sc.s_score) is null then 0 else avg(sc.s_score) end),2) "平均分" from student st
left join score sc on sc.s_id=st.s_id
group by st.s_id order by sc.s_score desc) a-- 25、查询各科成绩前三名的记录
select a.* from (select st.s_id,st.s_name,c.c_id,c.c_name,sc.s_score from student stleft join score sc on sc.s_id=st.s_idinner join course c on c.c_id=sc.c_id and c.c_id='01'order by sc.s_score desc LIMIT 0,3) a
union all 
select b.* from (select st.s_id,st.s_name,c.c_id,c.c_name,sc.s_score from student stleft join score sc on sc.s_id=st.s_idinner join course c on c.c_id=sc.c_id and c.c_id='02'order by sc.s_score desc LIMIT 0,3) b
union all
select c.* from (select st.s_id,st.s_name,c.c_id,c.c_name,sc.s_score from student stleft join score sc on sc.s_id=st.s_idinner join course c on c.c_id=sc.c_id and c.c_id='03'order by sc.s_score desc LIMIT 0,3) c-- 26、查询每门课程被选修的学生数 
select c.c_id,c.c_name,count(1) from course c 
left join score sc on sc.c_id=c.c_id
inner join student st on st.s_id=c.c_id
group by st.s_id-- 27、查询出只有两门课程的全部学生的学号和姓名
select st.s_id,st.s_name from student st 
left join score sc on sc.s_id=st.s_id
inner join course c on c.c_id=sc.c_id 
group by st.s_id having count(1)=2-- 28、查询男生、女生人数
select st.s_sex,count(1) from student st group by st.s_sex-- 29、查询名字中含有"风"字的学生信息
select st.* from student st where st.s_name like "%%";-- 30、查询同名同性学生名单,并统计同名人数 
select st.*,count(1) from student st group by st.s_name,st.s_sex having count(1)>1-- 31、查询1990年出生的学生名单
select st.* from student st where st.s_birth like "1990%";-- 32、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列 
select c.c_id,c.c_name,avg(sc.s_score) from course c
inner join score sc on sc.c_id=c.c_id  
group by c.c_id order by avg(sc.s_score) desc,c.c_id asc-- 33、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
select st.s_id,st.s_name,avg(sc.s_score) from student st
left join score sc on sc.s_id=st.s_id
group by st.s_id having avg(sc.s_score)>=85-- 34、查询课程名称为"数学",且分数低于60的学生姓名和分数 
select st.s_id,st.s_name,sc.s_score from student st
inner join score sc on sc.s_id=st.s_id and sc.s_score<60
inner join course c on c.c_id=sc.c_id and c.c_name ="数学" -- 35、查询所有学生的课程及分数情况;
select st.s_id,st.s_name,c.c_name,sc.s_score from student st
left join score sc on sc.s_id=st.s_id
left join course c on c.c_id =sc.c_id
order by st.s_id,c.c_name-- 36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数
select st2.s_id,st2.s_name,c2.c_name,sc2.s_score from student st2
left join score sc2 on sc2.s_id=st2.s_id
left join course c2 on c2.c_id=sc2.c_id 
where st2.s_id in(
select st.s_id from student st 
left join score sc on sc.s_id=st.s_id 
group by st.s_id having min(sc.s_score)>=70)
order by s_id-- 37、查询不及格的课程
select st.s_id,c.c_name,st.s_name,sc.s_score from student st
inner join score sc on sc.s_id=st.s_id and  sc.s_score<60
inner join course c on c.c_id=sc.c_id -- 38、查询课程编号为01且课程成绩在80分以上的学生的学号和姓名
select st.s_id,st.s_name,sc.s_score from student st
inner join score sc on sc.s_id=st.s_id and sc.c_id="01" and sc.s_score>=80-- 39、求每门课程的学生人数
select c.c_id,c.c_name,count(1) from course c
inner join score sc on sc.c_id=c.c_id
group by c.c_id-- 40、查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩 
select st.*,c.c_name,sc.s_score,t.t_name from student st
inner join score sc on sc.s_id=st.s_id
inner join course c on c.c_id=sc.c_id 
inner join teacher t on t.t_id=c.t_id and  t.t_name="张三"
order by sc.s_score desc
limit 0,1-- 41、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩 
select st.s_id,st.s_name,sc.c_id,sc.s_score from student st 
left join score sc on sc.s_id=st.s_id
left join course c on c.c_id=sc.c_id
where (
select count(1) from student st2 
left join score sc2 on sc2.s_id=st2.s_id
left join course c2 on c2.c_id=sc2.c_id
where sc.s_score=sc2.s_score and c.c_id!=c2.c_id 
)>1-- 42、查询每门功成绩最好的前两名 
select a.* from (select st.s_id,st.s_name,c.c_name,sc.s_score from student st
left join score sc on sc.s_id=st.s_id
inner join course c on c.c_id=sc.c_id and c.c_id="01"
order by sc.s_score desc limit 0,2) a
union all
select b.* from (select st.s_id,st.s_name,c.c_name,sc.s_score from student st
left join score sc on sc.s_id=st.s_id
inner join course c on c.c_id=sc.c_id and c.c_id="02"
order by sc.s_score desc limit 0,2) b
union all
select c.* from (select st.s_id,st.s_name,c.c_name,sc.s_score from student st
left join score sc on sc.s_id=st.s_id
inner join course c on c.c_id=sc.c_id and c.c_id="03"
order by sc.s_score desc limit 0,2) c-- 借鉴(更准确,漂亮):select a.s_id,a.c_id,a.s_score from score awhere (select COUNT(1) from score b where b.c_id=a.c_id and b.s_score>=a.s_score)<=2 order by a.c_id-- 43、统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,
--     若人数相同,按课程号升序排列  
select sc.c_id,count(1) from score sc
left join course c on c.c_id=sc.c_id
group by c.c_id having count(1)>5
order by count(1) desc,sc.c_id asc-- 44、检索至少选修两门课程的学生学号 
select st.s_id from student st 
left join score sc on sc.s_id=st.s_id
group by st.s_id having count(1)>=2-- 45、查询选修了全部课程的学生信息
select st.* from student st 
left join score sc on sc.s_id=st.s_id
group by st.s_id having count(1)=(select count(1) from course)-- 46、查询各学生的年龄select st.*,timestampdiff(year,st.s_birth,now()) from student st-- 47、查询本周过生日的学生-- 此处可能有问题,week函数取的为当前年的第几周,2017-12-12是第50周而2018-12-12是第49周,可以取月份,day,星期几(%w),-- 再判断本周是否会持续到下一个月进行判断,太麻烦,不会写
select st.* from student st 
where week(now())=week(date_format(st.s_birth,'%Y%m%d'))-- 48、查询下周过生日的学生
select st.* from student st 
where week(now())+1=week(date_format(st.s_birth,'%Y%m%d'))-- 49、查询本月过生日的学生
select st.* from student st 
where month(now())=month(date_format(st.s_birth,'%Y%m%d'))-- 50、查询下月过生日的学生-- 注意:当 当前月为12时,用month(now())+1为13而不是1,可用timestampadd()函数或mod取模
select st.* from student st 
where month(timestampadd(month,1,now()))=month(date_format(st.s_birth,'%Y%m%d'))
--
select st.* from student st where (month(now()) + 1) mod 12 = month(date_format(st.s_birth,'%Y%m%d'))

 

 

 三.记忆复苏(习题解析)

  3.1(Q1)

    left join是连接,貌似是自然连接(不想翻笔记了)。下面是左连接的语法(右连接类似):

SELECT *
FROM 左表格
LEFT JOIN 右表格 ON 连接条件

    只要看过相关书籍都知道select,from,where都是有一个执行顺序的,该顺序是from->where->select,每一条语句都是为了建立一个表(可以这么粗略理解),那么这道题的答案可以理解成

st表是左边的表,sc是右边的表,两个表的行进行自由组合(还是要注意哪些字段是哪些表的),我们需要找出来的就是sc_s_id = st.s_id (也就是提供了sc的对同id的其他信息的补充)的那些行st.c_id = '01'以及然后新建成一个无名表a1(from和join的成果,join可以理解成是from模块里面的,所以不要加逗号),然后在该无名表a1中寻找where条件符合的行再度新建成一个无名表a2(where),然后再在无名表a2中寻找select中提到的列新建一个无名表a3(结果)。

    这是Q1的结果:

                      

  3.3(Q3)

    比较重要的是分组,group by是将新建成的表模拟分组,一般搭配having使用,having是用来筛选符合having条件的组的,注意只是模拟分组,我们的表名还是可以用的,并不是说之后只能用group来代替。比如select语句:select st.s_id,st.s_name,ROUND(AVG(sc.s_score),2) cjScore

这一句中的sc.s_score使用了表名,同时这里的s_score是某一组的。

    使用分组的前提是想要切割一个表(而不用用到另外的表),注意事项是group by的内容必须是select里面的内容之一。

ps:ROUND(AVG(sc.s_score),2) cjScore中的cjScore是别名,关键字一般是as,但是用的时候在各模块经常省略as,group by可以理解是where模块的(只是我个人理解)

    ROUND(AVG(sc.s_score),2)表示对平均分数进行四舍五入,并保留两位小数。

    然后结果仍然是表。

    3.4(Q4)

    答案比Q3多了一个语句,case--when--then--end

CASEWHEN condition1 THEN result1WHEN condition2 THEN result2...ELSE default_result
END

    (话说这些东西可以去问gpt的,gpt虽然不太智能,但是很渊博)

     建议多加别名,否则就会这样。

      select的内容都是列。

  3.5(Q5)

      也可以这么做。

select st.s_id , st.s_name ,count(sc.c_id),
(case
when sum(sc.s_score) is null
then 0
else sum(sc.s_score)
end) all_score
from student st
left join score sc on st.s_id = sc.s_id
group by st.s_id;

  3.6(Q6)

    这里用到的是like关键字。LIKE 关键字用于模糊匹配,"李%" 表示以“李”开头的任意字符串。having关键字什么的就不讲了

  3.7(Q7)

    书写表的顺序推荐是从st到'张三“,这样子好写别名。

  3.8(Q8)

    可以使用嵌套select,也可以使用 联合查询。

    嵌套select使用的思路是从里到外,张老师的id,这个id对应的课程id,选课中有这个课程id的学生id,在student表中没有在求到的学生id范围中的学生id。

select st.*
from student st
where st.s_id not in(select sc.s_idfrom score scwhere sc.c_id  in(select c.c_idfrom course cwhere t_id = (select t_idfrom teacher tewhere t_name = '张三'))
);

     联合查询:思路是学过老师课程id的学生的表和student表join一下,null的那些就是没有选老师课程id的学生,建表返回相关学生信息。   

select st.*
from student st
left join(select distinct sc.s_idfrom score scjoin course c on sc.c_id = c.c_idjoin teacher te on te.t_id = c.t_idwhere te.t_name = '张三'
)learned_st on st.s_id = learned_st.s_id
where learned_st.s_id is null;

    这是联合查询的结果:(不同人数据都不太一样,所以只参考一下自己的表)

                          

     这里说一下left 和join之间的区别,left join是将from 里面的表放左边,如果右边的表行数不够(比如说学过选修课的学生id肯定比学生总数id少),left join会返回左边表的行数,即使右边表被填充了null也会返回;而join是全部返回(谁行数大就返回多少行)

    我尝试性地把st表放在右边,得到的结果验证了我的想法。

     

  3.9(Q9)

      inner join是指将匹配的行返回,只会讲匹配的行返回,所以不会有null的。我看了一下别人的例子:https://www.cnblogs.com/pcjim/articles/799302.html(先去看这个链接,下面的只是我做笔记用的)

举例如下:
--------------------------------------------
表A记录如下:
aID     aNum
1     a20050111
2     a20050112
3     a20050113
4     a20050114
5     a20050115

表B记录如下:
bID     bName
1     2006032401
2     2006032402
3     2006032403
4     2006032404
8     2006032408

--------------------------------------------
1.left join
sql语句如下:
select * from A
left join B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404
5     a20050115    NULL     NULL

(所影响的行数为 5 行)
--------------------------------------------
2.right join
sql语句如下:
select * from A
right join B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404
NULL     NULL     8     2006032408

(所影响的行数为 5 行)
--------------------------------------------
3.inner join
sql语句如下:
select * from A
innerjoin B
on A.aID = B.bID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404

    inner join绝对不会出现null,适合多重“学过”题目,如果是left join和right join由于有null,适合单个“学过”题目,

当然也不一定要牢记这个规则,后面学得熟悉了就不是很在意了。

    这道题的思路是先找学过编号01的再去找这之中学过编号02的。

    网友提供的做法中,思路一看就清楚了,所以HAVING SUM(IF(sc.`c_id`="01" OR sc.`c_id`="02" ,1,0))>1。筛选出sum大于1的,据此我们可以知道,if语句是某组一行一行地找,然后having 语句是对应的某组整个情况,所以一般搭配的是sum,avg等。对于这个答案我觉得还是加一个distinct比较好一点。

   

  3.10(Q10)

    我觉得这个答案太繁琐了。换成了这个。

 

SELECT st.*
FROM student st
LEFT JOIN score sc1 ON st.s_id = sc1.s_id AND sc1.c_id = '01'
LEFT JOIN score sc2 ON st.s_id = sc2.s_id AND sc2.c_id = '02'
WHERE sc1.c_id = '01' AND sc2.c_id IS NULL;

    

  3.12(Q12)

    特地列出来是因为我在这里写错了一种写法,目前来说并不知道错哪里了。

    现在回想起来,我为什么要写group呢(好像是因为重复的st_id有很多行,我下意识就group了)(不是having中c_id中别名的问题,事实上我试了很多次,这只是其中的一次尝试),gpt给的答案是

在 SQL 查询中,WHERE 子句用于过滤行,而 HAVING 子句用于过滤组。当使用 LEFT JOIN 连接表时,确实需要注意可能出现的 NULL 值对查询结果的影响。

WHERE 子句在查询过程中对行进行过滤,因此,如果 WHERE 子句中涉及到 LEFT JOIN 的列,数据库会考虑到 NULL 值,并根据条件过滤相应的行。但是,HAVING 子句在查询的结果已经分组后进行条件过滤,而且通常用于聚合函数结果的筛选,这时对于包含 NULL 值的列的判断就更为敏感。

在您的情况下,成功的查询使用了 WHERE 子句,并通过子查询来过滤了 sc.c_id。由于 WHERE 子句在过滤行时会考虑到 NULL 值,因此您的查询结果可能符合预期。

总的来说,无论是在 WHERE 子句还是 HAVING 子句中,都需要注意 LEFT JOIN 可能导致的 NULL 值,并根据具体情况进行处理,以确保查询结果的正确性。

    之后注意一下就行了。

  3.12(Q12)

    GROUP_CONCAT 是一个聚合函数,它用于将组内的多个值连接成一个字符串,并返回一个包含所有值的单个字符串。 

  3.15(Q15)

    

  3.17&3.18(Q17&Q18)(需要记住)

    一些感悟:join的on不也是将表的一部分分给其他表吗?确实嗷。给予的是其他表的信息。如果要求不同的东西却要

使用同一张原始的表,那么就建立不同的表也就是left join多次。

    在Q18中,答案极其复杂。group by使得c.c_id该列不会重复那么多行(其实这里用group还因为使用了聚合函数),将聚合函数扔掉。会有这个结果:

     还有这些:,((select count(s_id) from score where s_score>=60 and c_id=c.c_id )/(select count(s_id) from score where c_id=c.c_id)) "及格率" ,((select count(s_id) from score where s_score>=70 and s_score<80 and c_id=c.c_id )/(select count(s_id) from score where c_id=c.c_id)) "中等率" ,((select count(s_id) from score where s_score>=80 and s_score<90 and c_id=c.c_id )/(select count(s_id) from score where c_id=c.c_id)) "优良率" ,((select count(s_id) from score where s_score>=90 and c_id=c.c_id )/(select count(s_id) from score where c_id=c.c_id)) "优秀率"

    这些语句中我忧郁的就是及格率等没办法按照课程号来怎么办,最后纠结的时候发现了有添加 c_id=c.c_id,意义大家都知道了。

  3.19(Q19)

select c1.s_id,c1.c_id,c1.c_name,@score:=c1.s_score,@i:=@i+1 from (select c.c_name,sc.* from course c left join score sc on sc.c_id=c.c_id where c.c_id="01" order by sc.s_score desc) c1:

这个子查询选择了课程编号为 "01" 的课程信息,并将课程成绩降序排列。
使用了 MySQL 中的用户变量 @score 和 @i 来存储成绩和排名,@score 用于存储当前成绩,@i 用于记录排名。
通过 @i:=@i+1 语法,在结果中添加了一个排名列,按照成绩降序排列。
(select @i:=0) a:

这个子查询用于初始化变量 @i,将其值设为 0。
union all:

UNION ALL 操作符用于合并多个 SELECT 结果集,并包括重复行。
并不会打乱查询集里的顺序,只是为了代码健全度最好加一下@score。
同样的逻辑被重复了两次,用于查询课程编号为 "02" 和 "03" 的课程信息,并分别进行排名。

set @iii=0;:

最后,这个语句初始化了另一个用户变量 @iii,将其值设为 0

  3.26(Q26)

    count(1)和count(*)一样。

  3.29(Q29)

    %表示可以匹配任意字符串(包括零长度)

  3.30(Q30)这一道题记一下

  3.32(Q32)这一道题记一下

  3.36(Q36)这一道题记一下

  3.41(Q41)这一道题记一下

    子查询可以使用父查询的别名。这一道题的思路是,语句是一行行地遍历搜索的,所以如果该同学的某些条件和子查询(也就是另一些同学)如果有相似之处那么就会输出    

  3.42(Q42)这一道题记一下,借鉴写法写得很好(但是感觉可以改进)

  3.46(Q46)

    TIMESTAMPDIFF(YEAR, st.s_birth, NOW()): 这是一个函数调用,它计算了学生的年龄。TIMESTAMPDIFF函数的语法是TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2),它返回datetime_expr2datetime_expr1之间的差值,单位由unit指定。在这个查询中,unitYEARdatetime_expr1是学生的出生日期st.s_birthdatetime_expr2是当前日期NOW()。因此,该函数计算了学生的出生日期与当前日期之间的年数差值,即学生的年龄。

  3.47&3.48&3.49(Q47&Q.48&Q.49)

    都是类似的题目,只给上47的解析。

WEEK(NOW()) 返回当前日期所在的周数。
DATE_FORMAT(st.s_birth,'%Y%m%d') 用于将学生的生日按照年月日的格式表示。
WEEK() 函数用于计算日期所在的周数。
通过将当前日期的周数与学生生日的周数进行比较,来判断学生是否在本周过生日。
SELECT st.* 选择符合条件的所有学生信息。
因此,该查询将返回在本周过生日的学生的信息。

  3.50(Q50)这一道题记一下

    TIMESTAMPADD(MONTH, 1, NOW()) 是将当前日期增加一个月。也就是说

    

 

  四、感受

      好耶写完了。

 

参考链接:Mysql Sql 语句练习题 (50道) - 梅花GG - 博客园 (cnblogs.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/51320386.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

关于钉钉直播回放视频下载若干方法的总结

钉钉直播回放视频下载的基本步骤分为两步,第一步获取m3u8链接或文件,第二步使用m3u8链接或文件下载合并钉钉视频。根据钉钉客户端、版本的不同,以及使用获取m3u8方式的而不同,我总结了三种下载钉钉直播回放视频的方法,具体如下: 获取m3u8链接的几种方式 Fiddler+vconsle抓…

Ubuntu源哪个速度快?镜像站速度比拼!

Ubuntu镜像站网速比拼 先放结论:科大>腾讯云>清华 实验环境 宽带规格:广州联通,带宽1000M。 测试方法:使用vmware workstation 17安装Ubuntu 23.10虚拟机,打上快照。依次切换用不同的镜像源进行更新(sudo apt update && sudo apt upgrade),单个源更新过程中…

实验1 C语言开发环境使用和数据类型、运算符、表达式

task1点击查看代码 #include <stdio.h>int main() {printf(" o\n");printf("<H>\n");printf("I I\n");printf(" o\n");printf("<H>\n");printf("I I\n");system("pause");return 0; …

Packet for query is too large解决方案

华为云开发者联盟 Packet for query is too large (5,196,813 > 4,194,304). You can change this value on the server by se Packet for query is too large (5,196,813 > 4,194,304). You can change this value on the server by se 处理办法:1. 先查询,会看见一个现…

LeetCode[题解] 1261. 在受污染的二叉树中查找元素

首先我们看原题 给出一个满足下述规则的二叉树:root.val == 0 如果 treeNode.val == x 且 treeNode.left != null,那么 treeNode.left.val == 2 * x + 1 如果 treeNode.val == x 且 treeNode.right != null,那么 treeNode.right.val == 2 * x + 2现在这个二叉树受到「污染」…

【PR】UC-NERF: NEURAL RADIANCE FIELD FOR UNDERCALIBRATED MULTI-VIEW CAMERAS IN AUTONOMOUS DRIVING

【简介】 这篇文章的作者来自中科大、北大武汉人工智能研究院、大疆和上海科大,投稿到了ICLR 2024会议,已接收。 UC,表示under calibrated,意味着标定不准。本文提出UC-NeRF用于解决标定不够好的多相机配置的新视角合成方法。首先,作者提出一种基于层的颜色校正方法,以纠…