二、SQL系列之~常见51道SQL查询语句
【写在前面~~】
【PS1:建议SQL初学者一定要自己先做一遍题目,这样才有效果~~(做题时为验证查询结果是否正确,可更改表中数据)】
【PS2:文末最后一条代码整合了全部51道题目及答案~~】
【PS3:题目是网上所找,文中代码为自己练习编写,若有错误,请尽情指出~~】
一、创建数据库
create database 测试1 on primary
(name='测试1.mdf',
filename='E:\学习\SQL\实例目录\DATA\测试1.mdf',
SIZE=5MB,
MAXSIZE=UNLIMITED,
FILEGROWTH=1KB)
LOG ON
(NAME='测试1.ldf',
filename='E:\学习\SQL\实例目录\DATA\测试1.ldf',
size=520kb,
maxsize=unlimited,
filegrowth=20kb)
二、创建表
列名 | 类型 | 是否为空值 | 键约束 |
sid (学生编号) | int | 否 | 主键 |
sname (学生姓名) | varchar(10) | ||
sage( 出生年月) | datetime | ||
ssex (性别) |
varchar(10) |
列名 | 类型 | 是否为空值 | 键约束 |
tid (教师编号) | int | 否 | 主键 |
tname (教师姓名) | varchar(10) |
列名 | 类型 | 是否为空值 | 键约束 |
cid (课程编号) | int | 否 | 主键 |
cname (课程名) | varchar(10) | ||
tid (教师编号) | int | 外键 |
列名 | 类型 | 是否为空值 | 键约束 |
sid (学生编号) | int | 外键 | |
cid (课程编号) | int | 外键 | |
score (分数) | decimal(5,2) |
use 测试1
go
create table student
(sid varchar(10) not null constraint pk_sid primary key,
sname varchar(10),
sage datetime,
ssex varchar(10) constraint ck_ssex check (ssex in ('男','女')))--设置检查约束,性别一列只能输入男或女 create table teacher
(tid varchar(10) not null constraint pk_tid primary key ,
tname varchar(10)) create table course
(cid varchar(10) not null constraint pk_cid primary key,
cname varchar(10),
tid varchar(10) constraint fk_tid foreign key (tid) references teacher (tid))--tid 作为外键,引用teacher表中的主键tid create table sc
(sid varchar(10) constraint fk_sid foreign key (sid) references student(sid),
cid varchar(10) constraint fk_cid foreign key(cid) references course(cid),
score decimal(5,2))
insert into student values('' , '赵雷' , '1990-01-01' , '男')
insert into student values('' , '钱电' , '1990-12-21' , '男')
insert into student values('' , '孙风' , '1990-06-20' , '男')
insert into student values('' , '李云' , '1990-08-06' , '男')
insert into student values('' , '周梅' , '1991-12-01' , '女')
insert into student values('' , '吴兰' , '1992-03-01' , '女')
insert into student values('' , '郑竹' , '1989-06-04' , '女')
insert into student values('' , '王菊' , '1990-05-28' , '女')
insert into student values('' , '风王' , '1989-05-29' , '男')
insert into student values('' , '司徒风风' , '1991-06-05' , '女')
insert into student values('' , '桂易' , '1999-06-21' , '男')
insert into student values('' , '司徒末' , '1991-07-30' , '女')
insert into student values('' , '风王' , '1995-05-30' , '男')
insert into student values('' , '顾唯一' , '1998-06-02' , '男')
insert into student values('' , '圆圆' , '2000-06-06' , '女')
insert into student values('' , '司徒叮当' , '1997-06-03' , '女')
insert into student values('' , '顾未易' , '1999-06-12' , '男')
insert into student values('' , '顾未易' , '1999-06-08' , '男') insert into teacher values('' , '张三')
insert into teacher values('' , '李四')
insert into teacher values('' , '王五') insert into course values('' , '语文' , '')
insert into course values('' , '数学' , '')
insert into course values('' , '英语' , '')
insert into course values('' , '政治' , '')
insert into course values('' , '物理' , '') insert into SC values('' , '' , 80)
insert into SC values('' , '' , 90)
insert into SC values('' , '' , 99)
insert into SC values('' , '' , 80)
insert into SC values('' , '' , 60)
insert into SC values('' , '' , 80)
insert into SC values('' , '' , 80)
insert into SC values('' , '' , 80)
insert into SC values('' , '' , 80)
insert into SC values('' , '' , 80)
insert into SC values('' , '' , 30)
insert into SC values('' , '' , 90)
insert into SC values('' , '' , 76)
insert into SC values('' , '' , 87)
insert into SC values('' , '' , 31)
insert into SC values('' , '' , 34)
insert into SC values('' , '' , 90)
insert into SC values('' , '' , 98)
insert into SC values('' , '' , 90)
insert into SC values('' , '' , 50)
insert into SC values('' , '' , 60) select student.*,course.*,teacher.tname,sc.score into newtable
from student left join sc on student.sid=sc.sid left join course on course.cid= sc.cid left join teacher on teacher.tid=course.tid --将所有信息合在一起,为了后面查看校验查询信息是否正确
--若插入数据时重复执行了(若没有设置主键约束情况下),导致在删除数据时无法删除,提示已更新或删除行值要么不能使该行成为唯一行,要么...,则可用临时表来实现删除重复数据
select 各列字段名或全部列用*表示 into #临时表名 from 原表名 group by 字段列表
truncate table 原表名
insert into 原表名 select*from #临时表名
drop table #临时表名
四、51道题目及答案
--1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数
--第一种方法
select student.*,m.score [01课程成绩], n.score [02课程成绩]from student
join (select sid,score from sc where cid='') m on student.sid=m.sid
join (select sid,score from sc where cid='')n on student.sid=n.sid
where m.score>n.score
--第二种方法
select student.*,m.[01课程成绩],m.[02课程成绩] from student,
(select sid,sum(case when cid='' then score else null end) [01课程成绩] ,--若else后面是0,则结果会输出有01课程无02课程的学生,若改为null则不会输出只有一门课程的学生成绩
sum(case when cid='' then score else null end) [02课程成绩]from sc group by sid) m
where student.sid=m.sid and m.[01课程成绩]>m.[02课程成绩]
--2、查询同时存在"01"课程和"02"课程的情况
select student.*,m.score [01课程成绩],n.score [02课程成绩] from student
join (select sid ,score from sc where cid='') m on student.sid=m.sid
join (select sid,score from sc where cid='') n on student.sid=n.sid
--3、查询存在"01"课程但可能不存在"02"课程的情况(不存在时显示为null)
select student.*,m.score,n.score from (select sid,score from sc where cid='') m left join student on student.sid=m.sid
left join (select sid,score from sc where cid='')n on student.sid=n.sid
--4、 查询不存在" 01 "课程但存在" 02 "课程的情况
select student.*,score from student join sc on student.sid=sc.sid where cid='' and student.sid not in (select sid from sc where cid='')
--5、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
select student.sid,sname,cast (avg(score) as decimal(5,2))平均成绩 from student join sc on student.sid=sc.sid
group by student.sid,sname having avg(score)>=60
--6、查询在sc表存在成绩的学生信息的SQL语句
--第一种
select distinct student.* from student join sc on student.sid=sc.sid
--第二种
select * from student where sid in (select sc.sid from sc )--IN()适合B表(括号内的表是B)比A表数据小的情况
--第三种
select * from student where exists (select sc.sid from sc where student.sid = sc.sid)--EXISTS()适合B表比A表数据大的情况
--7、查询在sc表中不存在成绩的学生信息的SQL语句
select * from student where sid not in (select sc.sid from sc )
--8、查询所有同学的学生编号、学生姓名、选课总数、所有课程的成绩总和(没成绩的显示为 null )
select student.sid,sname,count(cid) 选课总数 ,sum(score ) 所有课程成绩的总和 from student
left join sc on student.sid=sc.sid group by student.sid,sname
--9、查询「李」姓老师的数量
select count (tid) 李姓老师的数量 from teacher where tname like '李%'
--10、查询学过「张三」老师授课的同学的信息
select student.* from student join sc on student.sid=sc.sid
join course on course.cid=sc.cid
join teacher on teacher.tid=course.tid where tname='张三'
--11、查询没学过「张三」老师授课的同学的信息
select *from student where sid not in (select sc.sid from sc join course on course.cid=sc.cid
join teacher on teacher.tid=course.tid where tname='张三')
--12、查询没有学全所有课程的同学的信息
--第一种直接
select student.* from student left join sc on student.sid=sc.sid group by student.sid,sname,sage,ssex
having count(sc.cid)<(select count(course.cid) from course)
----第二种反向
select student.* from student where student.sid not in
(select sc.sid from sc group by sid having count(sc.cid)= (select count(cid) from course))
--13、查询至少有一门课与学号为"01"的同学所学相同的同学的信息
select distinct student.* from student join sc on student.sid=sc.sid
where cid in (select cid from sc where sid='') and student.sid!='' --in的意思是:等于其中的一个则输出该条相等数据,直至全部输出为止
--14、查询和" 01 "号的同学学习的课程完全相同的其他同学的信息
--(即所学课程数要一致,学的课程目录也要一致)
select student.* from student join
(select sid from sc group by sid having count(cid)=(select count(cid) from sc where sid='' )) m--控制大范围下学生所学课程数=01同学的课程数3个,例如:学4门课程的同学,其中3门与01同学相同,也满足后续程序,但是与01同学就不是完全相同的.
on student.sid=m.sid join sc on student.sid=sc.sid
where sc.cid in (select cid from sc where sid='') and student.sid!=''group by student.sid,sname,sage,ssex
having count(sc.cid)=(select count(sc.cid) from sc where sid='')--控制与01同学所学课程目录相同的数也是3个
--15、查询没学过"张三"老师讲授的任一门课程的学生姓名
select * from student where student.sid not in
(select sc.sid from sc join course on sc.cid=course.cid
join teacher on teacher.tid=course.tid where tname='张三' )
--16、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
--第一种
select student.sid,sname,cast(avg(score) as decimal(5,2)) avgscore from student join sc
on student.sid=sc.sid where sc.score<60 group by student.sid,sname having count(sc.cid)>=2
--第二种
select student.sid,sname,cast(avg(score) as decimal(5,2)) avgscore from student join sc
on student.sid=sc.sid group by student.sid,sname having sum(case when score<60 then 1 else 0 end)>=2
--17、检索"01"课程分数小于60,按分数降序排列的学生信息
select student.* from student join sc on student.sid=sc.sid where cid='' and score<60 order by score desc
--18、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
select student.sid,sname, sc.cid,sc.score,m.avgscore from student left join sc on student.sid=sc.sid
left join (select sid,cast(avg(score) as decimal(5,2)) avgscore from sc group by sid ) m on sc.sid=m.sid
order by m.avgscore desc
--19、查询各科成绩最高分、最低分和平均分:
--以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
--(及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90)
select sc.cid,course.cname,max(sc.score) 最高分,min(sc.score) 最低分,cast(avg(sc.score) as decimal(5,2)) 平均分 ,
count(sc.cid) 计数,
sum(case when sc.score>=60 then 1 else 0 end )及格数, sum(case when sc.score>=70 and sc.score<80 then 1 else 0 end ) 中等数,
sum(case when sc.score>=80 and sc.score<90 then 1 else 0 end ) 优良数,sum(case when sc.score>=90 then 1 else 0 end ) 优秀数,--这里的计数,及格数...优秀数是为了验证后续的及格率...优秀率是否正确的,完全按照题意需省去
convert(varchar(10),cast((100*sum(case when score>=60 then 1 else 0 end) /cast(count(sc.cid) as float)) as decimal(5,2)))+'%' 及格率,--分母count(sc.sid)要转化为浮点型数据,否则分子是整数,结果也为整数,舍小数位或者把分子转化为浮点型数据,结果也会为浮点型
convert(varchar(10),cast((100*sum(case when sc.score>=70 and sc.score<80 then 1 else 0 end) /cast(count(sc.cid) as float)) as decimal(5,2)))+'%' 中等率,
convert(varchar(10),cast((100*sum(case when sc.score>=80 and sc.score<90 then 1 else 0 end) /cast(count(sc.cid) as float)) as decimal(5,2)))+'%' 优良率,
convert(varchar(10),cast((100*sum(case when sc.score>=90 then 1 else 0 end) /cast(count(sc.cid) as float)) as decimal(5,2)))+'%' 优秀率
from course join sc on course.cid=sc.cid group by sc.cid,course.cname
--20、按各科成绩进行排序,并显示排名,score 重复时保留名次空缺
--第一种
select a.cid,a.sid,a.score,count(b.score) +1 排名 from sc a
left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score order by a.cid asc,排名 asc
---select a.cid,a.sid,a.score,b.score from sc a left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score,b.score 在课程相同的情况下,计算比自己分数大的有几个再加上1即为排名
--例如课程3,学号1,99;2,80;3,80;4,90;6,34;7,98
--则对应的比1,99大的为null排名1;比2,80大的为99,90,98排名4;比3,80大的99,90,98排名3;比4,90大的为99,98排名3;比6,34大的为99,90,98,80,80排名6;比7,98大的为99排名2 --第二种(使用内置函数rank)
select cid,sid,score,rank() over (partition by cid order by score desc ) 排名 from sc --partition by 分组 order by 排序
--21、按各科成绩进行排序,并显示排名,score 重复时合并名次空缺
--第一种
select a.cid,a.sid,a.score,count(distinct b.score) +1 排名 from sc a
left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score order by a.cid asc,排名 asc
--第二种(使用内置函数dense_rank)
select cid,sid,score,dense_rank() over (partition by cid order by score desc ) 排名 from sc
--22、查询学生的总成绩,并进行排名,总分重复时合并名次空缺
--第一种
select a.sid,a.allscore 总成绩,count(distinct b.allscore)+1 排名 from ( select sid,sum(score) allscore from sc group by sid) a
left join ( select sid,sum(score) allscore from sc group by sid) b on a.allscore<b.allscore group by a.sid,a.allscore order by 排名 asc
--a表与b表中已经进行完全相同的学生sid分组,在左连接时不应再让sid相等连接,否则左连接时b.allscore >a.allscore匹配为空值,每个学生的排名都为1,即在学号sid相等情况,不能再比较不同学生间的成绩排名,只能自我比较
--而20/21题的第一种方法有cid左连接相等即在同一课程下,还可以比较不同学生sid间的成绩排名
--第二种
select sid,sum(score) 总成绩 ,dense_rank()over(order by sum(score) desc ) 排名 from sc group by sid
--这里的成绩不是所有同学sid的成绩,有的同学没有成绩,因此我们可以将student与上述两种方法进行左连接--例如:
select a.sid ,a.allscore 总成绩,count(distinct b.allscore)+1 排名 from
(select student.sid ,isnull(sum(score),0) allscore from student left join sc on student.sid=sc.sid group by student.sid ) a left join
(select student.sid ,isnull(sum(score),0) allscore from student left join sc on student.sid=sc.sid group by student.sid ) b on a.allscore<b.allscore
group by a.sid,a.allscore order by 排名 asc select student.sid,isnull(sum(score),0) 总成绩,dense_rank()over(order by isnull(sum(score),0) desc )排名
from student left join sc on student.sid=sc.sid group by student.sid
--23、查询不同老师所教不同课程平均分从高到低显示
select course.tid,tname,course.cid,cast(avg(score) as decimal(5,2)) 课程平均分 from course left join sc on sc.cid=course.cid
left join teacher on teacher.tid=course.tid group by course.tid ,tname,course.cid order by avg(score) desc
--24、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
--第一种
select student.*,m.cid,m.成绩,m.排名 from student left join
( select a.cid,a.sid,a.score 成绩,count(b.score)+1 排名 from sc a left join sc b on a.cid=b.cid and a.score<b.score
group by a.cid,a.sid,a.score ) m on m.sid=student.sid where m.排名 between 2 and 3 order by m.cid asc,排名 asc--重复排名时保留名次空缺,把count 内改成distinct b.score 即为重复时合并空缺
--第二种
select student.*,m.cid,m.成绩,m.排名 from student left join
(select cid,sid,score 成绩,rank()over(partition by cid order by score desc) 排名 from sc group by cid,sid,score) m
on student.sid=m.sid where m.排名 between 2 and 3 order by cid asc--rank 改为dense_rank 即为合并名次空缺
--25、查询各科成绩前三名的记录
--第一种
select a.cid,a.sid,a.score from sc a left join sc b on a.cid=b.cid and a.score<b.score
group by a.cid,a.sid,a.score having count(b.score)<3 order by a.cid asc ,a.score desc --成绩重复时保留名次空缺,输出排名为1-3的学生;也可以按照24题来做,排名改成between 1 and 3即可
--第二种
select cid,sid,score from sc a where sid in (
select top 3 b.sid from sc b where a.cid=b.cid order by b.cid asc ,b.score desc )
order by cid asc,score desc --这种top 型的只输出前3个学生,对于成绩重复的同一名次会缺失
--第三种
select * from
(select *,row_number()over(partition by cid order by score desc) 排名 from sc) B
where B.排名<4--同样只输出前3个学生,对于成绩重复的同一名次会缺失
--26、查询各科成绩最高的记录
select sc.cid, sc.sid,m.maxscore from sc join (select cid,max(score) maxscore from sc group by cid ) m
on m.maxscore=sc.score and m.cid=sc.cid
--其余方法可参直接参考25题方法
--27、查询选修一门以上且不包括最高成绩学生的其余学生成绩
--第一种
select sid,cid,score from sc where sid not in (select sc.sid from sc join (select cid,max(score) maxscore from sc group by cid ) m
on m.maxscore=sc.score and m.cid=sc.cid ) and sid in (select sid from sc group by sid having count (sid)>1)
--第二种
select sid,cid,score from sc where sid not in
( select a.sid from sc a left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score having count(b.score)=0)
and sid in (select sid from sc group by sid having count (sid)>1)
--若改成-选修一门以上不是最高成绩的其余成绩(还包括最高成绩的学生的其他科目成绩)--每科成绩非最高分的记录
select cid,sid,score from sc a where sid not in (
select top 3 b.sid from sc b where a.cid=b.cid order by b.cid asc ,b.score desc )
and sid in (select sid from sc group by sid having count (sid)>1)
--28、查询每门课程被选修的学生数
select cid,count(sid) 选修人数 from sc group by cid
--29、查询出只选修两门课程的学生学号和姓名
select student.sid 学号,sname 姓名 from student join sc on student.sid=sc.sid group by student.sid,sname having count(student.sid)=2
--30、查询男生、女生人数
select ssex, count (ssex) 人数 from student group by ssex
--31、查询名字中含有"风"字的学生信息
select * from student where sname like '风%' or sname like '%风'
--32、查询同名同性学生名单,并统计同名人数
select a.sname,a.ssex,count(a.sname) 同名人数 from student a,student b
where a.sid!=b.sid and a.sname=b.sname and a.ssex=b.ssex group by a.sname,a.ssex
--33、查询1990年出生的学生名单
select * from student where datename(yy,sage)=''
--34、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select cid,cast(avg(score) as decimal(5,2)) avgscore from sc group by cid order by avgscore desc,cid asc
--35、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
select student.sid,sname,avg(score) from student
join sc on student.sid =sc.sid group by student.sid,sname having avg(score)>=85
--36、查询课程名称为"数学",且分数低于60的学生姓名和分数
select student.sname,score from student join sc on student.sid=sc.sid
join course on course.cid=sc.cid where cname='数学' and score <60
--37、查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
select student.*,cid,score from student left join sc on student.sid=sc.sid
--38、查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
select student.sid,course.cname,sc.score from student join sc on student.sid=sc.sid join course on course.cid=sc.cid where score>70
--39、查询存在不及格的课程
--第一种
select distinct cid from sc where score<60--distinct确定唯一性
--第二种
select cid from sc where score<60 group by cid--group by 确定唯一性
--40、查询课程编号为 01 且课程成绩在 80 分及以上的学生的学号和姓名
select student.sid,student.sname from student join sc on student.sid=sc.sid where cid='' and score>=80
--41、求每门课程的学生人数
--要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select cid,count(sid) 每门课程人数 from sc group by cid order by 每门课程人数 desc,cid asc
--42、成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select top 1 student.*,m.maxscore from student join (
select sid,max(score) maxscore from teacher join course on course.tid=teacher.tid join sc on sc.cid=course.cid
where tname='张三' group by sid ) m on student.sid=m.sid order by m. maxscore desc --若改成:每个教师所教每门课程的最高成绩
select m.tname,m.cid,sid,m.maxscore from sc join (
select tname,sc.cid,max(score) maxscore from teacher join course on course.tid=teacher.tid join sc on sc.cid=course.cid
group by tname,sc.cid) m on sc.cid=m.cid and sc.score=m.maxscore order by m.cid asc
--43、成绩重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select student.*,m.score from student join (
select a.cid,a.sid,a.score from sc a left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score having count(b.score)=0) m
on student.sid=m.sid join course on course.cid=m.cid join teacher on teacher.tid=course.tid where tname='张三'--m表内容也可以改成用rank函数做成排名,取排名第一即可
--44、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
select a.sid,a.cid,a.score from sc a join sc b on a.sid=b.sid where a.cid!=b.cid and a.score=b.score group by a.cid,a.sid,a.score
--45、查询选修了全部课程的学生信息
select student.* from student join
(select sid from sc group by sid having count(sc.cid)= (select count(cid) from course)) m
on student.sid=m.sid
--46、查询各学生的年龄,只按照年份来算
select student.*,datediff(yy,sage,getdate()) age from student
--47、查询各学生的年龄,按照出生日期来算,当前月日 < 出生年月的月日则年龄减一
--第一种
select *,
(case when convert(int,convert(varchar(10),getdate(),112))<convert (int,convert(varchar(10),year(getdate()))+substring(convert(varchar(10),sage,112),5,4))
then datediff(yy,sage,getdate())-1 else datediff(yy,sage,getdate()) end )age--出生年月变成现在的年与月日 同现在的时间对比大小
from student
--第二种
select *,(case when month(getdate())<month(sage) then datediff(yy,sage,getdate())-1
when month(getdate())=month(sage) and day(getdate())<day(sage) then datediff(yy,sage,getdate())-1
else datediff(yy,sage,getdate()) end) age from student
--第三种
select * , (case when right(convert(varchar(10),getdate(),120),5) < right(convert(varchar(10),sage,120),5)
then datediff(yy ,sage,getdate()) - 1 else datediff(yy ,sage, getdate()) end) age from student
--48、查询本周过生日的学生
--第一种
select *,(case when datename(wk,convert(datetime,(convert(varchar(10),year(getdate()))+substring(convert(varchar(10),sage,112),5,4))))=
datename(wk,getdate()) then 1 else 0 end) 生日提醒 from student
--第二种
select * from student where datediff(wk,datename(yy,getdate()) + right(convert(varchar(10),sage,120),6),getdate()) = 0
49、查询下周过生日的学生
--第一种
select *,(case when datename(wk,convert(datetime,(convert(varchar(10),year(getdate()))+substring(convert(varchar(10),sage,112),5,4))))=
datename(wk,getdate())+1 then 1 else 0 end) 生日提醒 from student
--第二种
select * from student where datediff(wk,datename(yy,getdate()) + right(convert(varchar(10),sage,120),6),getdate()) = -1
--50、查询本月过生日的学生
--第一种
select * from student where month(getdate())=month(sage)
--第二种
select * from student where datediff(mm,datename(yy,getdate()) + right(convert(varchar(10),sage,120),6),getdate()) = 0
--51、查询下月过生日的学生
--第一种
select * from student where month(getdate())+1=month(sage)
--第二种
select * from student where datediff(mm,datename(yy,getdate()) + right(convert(varchar(10),sage,120),6),getdate()) = -1
【这是一条整合了全部51道题目及答案的代码】
--1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数
--第一种方法
select student.*,m.score [01课程成绩], n.score [02课程成绩]from student
join (select sid,score from sc where cid='') m on student.sid=m.sid
join (select sid,score from sc where cid='')n on student.sid=n.sid
where m.score>n.score
--第二种方法
select student.*,m.[01课程成绩],m.[02课程成绩] from student,
(select sid,sum(case when cid='' then score else null end) [01课程成绩] ,--若else后面是0,则结果会输出有01课程无02课程的学生,若改为null则不会输出只有一门课程的学生成绩
sum(case when cid='' then score else null end) [02课程成绩]from sc group by sid) m
where student.sid=m.sid and m.[01课程成绩]>m.[02课程成绩] --2、查询同时存在"01"课程和"02"课程的情况 select student.*,m.score [01课程成绩],n.score [02课程成绩] from student
join (select sid ,score from sc where cid='') m on student.sid=m.sid
join (select sid,score from sc where cid='') n on student.sid=n.sid --3、查询存在"01"课程但可能不存在"02"课程的情况(不存在时显示为null)
select student.*,m.score,n.score from (select sid,score from sc where cid='') m left join student on student.sid=m.sid
left join (select sid,score from sc where cid='')n on student.sid=n.sid --4、 查询不存在" 01 "课程但存在" 02 "课程的情况
select student.*,score from student join sc on student.sid=sc.sid where cid='' and student.sid not in (select sid from sc where cid='')
--5、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩
select student.sid,sname,cast (avg(score) as decimal(5,2))平均成绩 from student join sc on student.sid=sc.sid
group by student.sid,sname having avg(score)>=60
--6、查询在sc表存在成绩的学生信息的SQL语句
--第一种
select distinct student.* from student join sc on student.sid=sc.sid
--第二种
select * from student where sid in (select sc.sid from sc )--IN()适合B表(括号内的表是B)比A表数据小的情况
--第三种
select * from student where exists (select sc.sid from sc where student.sid = sc.sid)--EXISTS()适合B表比A表数据大的情况
--7、查询在sc表中不存在成绩的学生信息的SQL语句
select * from student where sid not in (select sc.sid from sc )
--8、查询所有同学的学生编号、学生姓名、选课总数、所有课程的成绩总和(没成绩的显示为 null )
select student.sid,sname,count(cid) 选课总数 ,sum(score ) 所有课程成绩的总和 from student
left join sc on student.sid=sc.sid group by student.sid,sname
--9、查询「李」姓老师的数量
select count (tid) 李姓老师的数量 from teacher where tname like '李%'
--10、查询学过「张三」老师授课的同学的信息
select student.* from student join sc on student.sid=sc.sid
join course on course.cid=sc.cid
join teacher on teacher.tid=course.tid where tname='张三' --11、查询没学过「张三」老师授课的同学的信息
select *from student where sid not in (select sc.sid from sc join course on course.cid=sc.cid
join teacher on teacher.tid=course.tid where tname='张三') --12、查询没有学全所有课程的同学的信息
--第一种直接
select student.* from student left join sc on student.sid=sc.sid group by student.sid,sname,sage,ssex
having count(sc.cid)<(select count(course.cid) from course)
----第二种反向
select student.* from student where student.sid not in
(select sc.sid from sc group by sid having count(sc.cid)= (select count(cid) from course))
--13、查询至少有一门课与学号为"01"的同学所学相同的同学的信息
select distinct student.* from student join sc on student.sid=sc.sid
where cid in (select cid from sc where sid='') and student.sid!='' --in的意思是:等于其中的一个则输出该条相等数据,直至全部输出为止
--14、查询和" 01 "号的同学学习的课程完全相同的其他同学的信息
--(即所学课程数要一致,学的课程目录也要一致)
select student.* from student join
(select sid from sc group by sid having count(cid)=(select count(cid) from sc where sid='' )) m--控制大范围下学生所学课程数=01同学的课程数3个,例如:学4门课程的同学,其中3门与01同学相同,也满足后续程序,但是与01同学就不是完全相同的.
on student.sid=m.sid join sc on student.sid=sc.sid
where sc.cid in (select cid from sc where sid='') and student.sid!=''group by student.sid,sname,sage,ssex
having count(sc.cid)=(select count(sc.cid) from sc where sid='')--控制与01同学所学课程目录相同的数也是3个
--15、查询没学过"张三"老师讲授的任一门课程的学生姓名
select * from student where student.sid not in
(select sc.sid from sc join course on sc.cid=course.cid
join teacher on teacher.tid=course.tid where tname='张三' )
--16、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
--第一种
select student.sid,sname,cast(avg(score) as decimal(5,2)) avgscore from student join sc
on student.sid=sc.sid where sc.score<60 group by student.sid,sname having count(sc.cid)>=2
--第二种
select student.sid,sname,cast(avg(score) as decimal(5,2)) avgscore from student join sc
on student.sid=sc.sid group by student.sid,sname having sum(case when score<60 then 1 else 0 end)>=2
--17、检索"01"课程分数小于60,按分数降序排列的学生信息
select student.* from student join sc on student.sid=sc.sid where cid='' and score<60 order by score desc
--18、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
select student.sid,sname, sc.cid,sc.score,m.avgscore from student left join sc on student.sid=sc.sid
left join (select sid,cast(avg(score) as decimal(5,2)) avgscore from sc group by sid ) m on sc.sid=m.sid
order by m.avgscore desc
--19、查询各科成绩最高分、最低分和平均分:
--以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
--(及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90)
select sc.cid,course.cname,max(sc.score) 最高分,min(sc.score) 最低分,cast(avg(sc.score) as decimal(5,2)) 平均分 ,
count(sc.cid) 计数,
sum(case when sc.score>=60 then 1 else 0 end )及格数, sum(case when sc.score>=70 and sc.score<80 then 1 else 0 end ) 中等数,
sum(case when sc.score>=80 and sc.score<90 then 1 else 0 end ) 优良数,sum(case when sc.score>=90 then 1 else 0 end ) 优秀数,--这里的计数,及格数...优秀数是为了验证后续的及格率...优秀率是否正确的,完全按照题意需省去
convert(varchar(10),cast((100*sum(case when score>=60 then 1 else 0 end) /cast(count(sc.cid) as float)) as decimal(5,2)))+'%' 及格率,--分母count(sc.sid)要转化为浮点型数据,否则分子是整数,结果也为整数,舍小数位或者把分子转化为浮点型数据,结果也会为浮点型
convert(varchar(10),cast((100*sum(case when sc.score>=70 and sc.score<80 then 1 else 0 end) /cast(count(sc.cid) as float)) as decimal(5,2)))+'%' 中等率,
convert(varchar(10),cast((100*sum(case when sc.score>=80 and sc.score<90 then 1 else 0 end) /cast(count(sc.cid) as float)) as decimal(5,2)))+'%' 优良率,
convert(varchar(10),cast((100*sum(case when sc.score>=90 then 1 else 0 end) /cast(count(sc.cid) as float)) as decimal(5,2)))+'%' 优秀率
from course join sc on course.cid=sc.cid group by sc.cid,course.cname --20、按各科成绩进行排序,并显示排名,score 重复时保留名次空缺
--第一种
select a.cid,a.sid,a.score,count(b.score) +1 排名 from sc a
left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score order by a.cid asc,排名 asc
---select a.cid,a.sid,a.score,b.score from sc a left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score,b.score 在课程相同的情况下,计算比自己分数大的有几个再加上1即为排名
--例如课程3,学号1,99;2,80;3,80;4,90;6,34;7,98
--则对应的比1,99大的为null排名1;比2,80大的为99,90,98排名4;比3,80大的99,90,98排名3;比4,90大的为99,98排名3;比6,34大的为99,90,98,80,80排名6;比7,98大的为99排名2 --第二种(使用内置函数rank)
select cid,sid,score,rank() over (partition by cid order by score desc ) 排名 from sc --partition by 分组 order by 排序
--21、按各科成绩进行排序,并显示排名,score 重复时合并名次空缺
--第一种
select a.cid,a.sid,a.score,count(distinct b.score) +1 排名 from sc a
left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score order by a.cid asc,排名 asc
--第二种(使用内置函数dense_rank)
select cid,sid,score,dense_rank() over (partition by cid order by score desc ) 排名 from sc --22、查询学生的总成绩,并进行排名,总分重复时合并名次空缺
--第一种
select a.sid,a.allscore 总成绩,count(distinct b.allscore)+1 排名 from ( select sid,sum(score) allscore from sc group by sid) a
left join ( select sid,sum(score) allscore from sc group by sid) b on a.allscore<b.allscore group by a.sid,a.allscore order by 排名 asc
--a表与b表中已经进行完全相同的学生sid分组,在左连接时不应再让sid相等连接,否则左连接时b.allscore >a.allscore匹配为空值,每个学生的排名都为1,即在学号sid相等情况,不能再比较不同学生间的成绩排名,只能自我比较
--而20/21题的第一种方法有cid左连接相等即在同一课程下,还可以比较不同学生sid间的成绩排名
--第二种
select sid,sum(score) 总成绩 ,dense_rank()over(order by sum(score) desc ) 排名 from sc group by sid
--这里的成绩不是所有同学sid的成绩,有的同学没有成绩,因此我们可以将student与上述两种方法进行左连接--例如:
select a.sid ,a.allscore 总成绩,count(distinct b.allscore)+1 排名 from
(select student.sid ,isnull(sum(score),0) allscore from student left join sc on student.sid=sc.sid group by student.sid ) a left join
(select student.sid ,isnull(sum(score),0) allscore from student left join sc on student.sid=sc.sid group by student.sid ) b on a.allscore<b.allscore
group by a.sid,a.allscore order by 排名 asc select student.sid,isnull(sum(score),0) 总成绩,dense_rank()over(order by isnull(sum(score),0) desc )排名
from student left join sc on student.sid=sc.sid group by student.sid --23、查询不同老师所教不同课程平均分从高到低显示
select course.tid,tname,course.cid,cast(avg(score) as decimal(5,2)) 课程平均分 from course left join sc on sc.cid=course.cid
left join teacher on teacher.tid=course.tid group by course.tid ,tname,course.cid order by avg(score) desc --24、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
--第一种
select student.*,m.cid,m.成绩,m.排名 from student left join
( select a.cid,a.sid,a.score 成绩,count(b.score)+1 排名 from sc a left join sc b on a.cid=b.cid and a.score<b.score
group by a.cid,a.sid,a.score ) m on m.sid=student.sid where m.排名 between 2 and 3 order by m.cid asc,排名 asc--重复排名时保留名次空缺,把count 内改成distinct b.score 即为重复时合并空缺
--第二种
select student.*,m.cid,m.成绩,m.排名 from student left join
(select cid,sid,score 成绩,rank()over(partition by cid order by score desc) 排名 from sc group by cid,sid,score) m
on student.sid=m.sid where m.排名 between 2 and 3 order by cid asc--rank 改为dense_rank 即为合并名次空缺 --25、查询各科成绩前三名的记录
--第一种
select a.cid,a.sid,a.score from sc a left join sc b on a.cid=b.cid and a.score<b.score
group by a.cid,a.sid,a.score having count(b.score)<3 order by a.cid asc ,a.score desc --成绩重复时保留名次空缺,输出排名为1-3的学生;也可以按照24题来做,排名改成between 1 and 3即可
--第二种
select cid,sid,score from sc a where sid in (
select top 3 b.sid from sc b where a.cid=b.cid order by b.cid asc ,b.score desc )
order by cid asc,score desc --这种top 型的只输出前3个学生,对于成绩重复的同一名次会缺失
--第三种
select * from
(select *,row_number()over(partition by cid order by score desc) 排名 from sc) B
where B.排名<4--同样只输出前3个学生,对于成绩重复的同一名次会缺失 --26、查询各科成绩最高的记录
select sc.cid, sc.sid,m.maxscore from sc join (select cid,max(score) maxscore from sc group by cid ) m
on m.maxscore=sc.score and m.cid=sc.cid
--其余方法可参直接参考25题方法 --27、查询选修一门以上且不包括最高成绩学生的其余学生成绩
--第一种
select sid,cid,score from sc where sid not in (select sc.sid from sc join (select cid,max(score) maxscore from sc group by cid ) m
on m.maxscore=sc.score and m.cid=sc.cid ) and sid in (select sid from sc group by sid having count (sid)>1)
--第二种
select sid,cid,score from sc where sid not in
( select a.sid from sc a left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score having count(b.score)=0)
and sid in (select sid from sc group by sid having count (sid)>1)
--若改成-选修一门以上不是最高成绩的其余成绩(还包括最高成绩的学生的其他科目成绩)--每科成绩非最高分的记录
select cid,sid,score from sc a where sid not in (
select top 3 b.sid from sc b where a.cid=b.cid order by b.cid asc ,b.score desc )
and sid in (select sid from sc group by sid having count (sid)>1) --28、查询每门课程被选修的学生数
select cid,count(sid) 选修人数 from sc group by cid --29、查询出只选修两门课程的学生学号和姓名
select student.sid 学号,sname 姓名 from student join sc on student.sid=sc.sid group by student.sid,sname having count(student.sid)=2
--30、查询男生、女生人数
select ssex, count (ssex) 人数 from student group by ssex
--31、查询名字中含有"风"字的学生信息
select * from student where sname like '风%' or sname like '%风'
--32、查询同名同性学生名单,并统计同名人数
select a.sname,a.ssex,count(a.sname) 同名人数 from student a,student b
where a.sid!=b.sid and a.sname=b.sname and a.ssex=b.ssex group by a.sname,a.ssex
--33、查询1990年出生的学生名单
select * from student where datename(yy,sage)=''
--34、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select cid,cast(avg(score) as decimal(5,2)) avgscore from sc group by cid order by avgscore desc,cid asc
--35、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩
select student.sid,sname,avg(score) from student
join sc on student.sid =sc.sid group by student.sid,sname having avg(score)>=85
--36、查询课程名称为"数学",且分数低于60的学生姓名和分数
select student.sname,score from student join sc on student.sid=sc.sid
join course on course.cid=sc.cid where cname='数学' and score <60
--37、查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
select student.*,cid,score from student left join sc on student.sid=sc.sid
--38、查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
select student.sid,course.cname,sc.score from student join sc on student.sid=sc.sid join course on course.cid=sc.cid where score>70
--39、查询存在不及格的课程
select distinct cid from sc where score<60--distinct确定唯一性
select cid from sc where score<60 group by cid--group by 确定唯一性
--40、查询课程编号为 01 且课程成绩在 80 分及以上的学生的学号和姓名
select student.sid,student.sname from student join sc on student.sid=sc.sid where cid='' and score>=80
--41、求每门课程的学生人数
--要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select cid,count(sid) 每门课程人数 from sc group by cid order by 每门课程人数 desc,cid asc
--42、成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select top 1 student.*,m.maxscore from student join (
select sid,max(score) maxscore from teacher join course on course.tid=teacher.tid join sc on sc.cid=course.cid
where tname='张三' group by sid ) m on student.sid=m.sid order by m. maxscore desc --若改成:每个教师所教每门课程的最高成绩
select m.tname,m.cid,sid,m.maxscore from sc join (
select tname,sc.cid,max(score) maxscore from teacher join course on course.tid=teacher.tid join sc on sc.cid=course.cid
group by tname,sc.cid) m on sc.cid=m.cid and sc.score=m.maxscore order by m.cid asc --43、成绩重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩
select student.*,m.score from student join (
select a.cid,a.sid,a.score from sc a left join sc b on a.cid=b.cid and a.score<b.score group by a.cid,a.sid,a.score having count(b.score)=0) m
on student.sid=m.sid join course on course.cid=m.cid join teacher on teacher.tid=course.tid where tname='张三'--m表内容也可以改成用rank函数做成排名,取排名第一即可 --44、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
select a.sid,a.cid,a.score from sc a join sc b on a.sid=b.sid where a.cid!=b.cid and a.score=b.score group by a.cid,a.sid,a.score --45、查询选修了全部课程的学生信息
select student.* from student join
(select sid from sc group by sid having count(sc.cid)= (select count(cid) from course)) m
on student.sid=m.sid
--46、查询各学生的年龄,只按照年份来算
select student.*,datediff(yy,sage,getdate()) age from student
--47、查询各学生的年龄,按照出生日期来算,当前月日 < 出生年月的月日则年龄减一
--第一种
select *,
(case when convert(int,convert(varchar(10),getdate(),112))<convert (int,convert(varchar(10),year(getdate()))+substring(convert(varchar(10),sage,112),5,4))
then datediff(yy,sage,getdate())-1 else datediff(yy,sage,getdate()) end )age--出生年月变成现在的年与月日 同现在的时间对比大小
from student
--第二种
select *,(case when month(getdate())<month(sage) then datediff(yy,sage,getdate())-1
when month(getdate())=month(sage) and day(getdate())<day(sage) then datediff(yy,sage,getdate())-1
else datediff(yy,sage,getdate()) end) age from student
--第三种
select * , (case when right(convert(varchar(10),getdate(),120),5) < right(convert(varchar(10),sage,120),5)
then datediff(yy ,sage,getdate()) - 1 else datediff(yy ,sage, getdate()) end) age from student
--48、查询本周过生日的学生
--第一种
select *,(case when datename(wk,convert(datetime,(convert(varchar(10),year(getdate()))+substring(convert(varchar(10),sage,112),5,4))))=
datename(wk,getdate()) then 1 else 0 end) 生日提醒 from student
--第二种
select * from student where datediff(wk,datename(yy,getdate()) + right(convert(varchar(10),sage,120),6),getdate()) = 0
--49、查询下周过生日的学生
--第一种
select *,(case when datename(wk,convert(datetime,(convert(varchar(10),year(getdate()))+substring(convert(varchar(10),sage,112),5,4))))=
datename(wk,getdate())+1 then 1 else 0 end) 生日提醒 from student
--第二种
select * from student where datediff(wk,datename(yy,getdate()) + right(convert(varchar(10),sage,120),6),getdate()) = -1
--50、查询本月过生日的学生
--第一种
select * from student where month(getdate())=month(sage)
--第二种
select * from student where datediff(mm,datename(yy,getdate()) + right(convert(varchar(10),sage,120),6),getdate()) = 0 --51、查询下月过生日的学生
--第一种
select * from student where month(getdate())+1=month(sage)
--第二种
select * from student where datediff(mm,datename(yy,getdate()) + right(convert(varchar(10),sage,120),6),getdate()) = -1
二、SQL系列之~常见51道SQL查询语句的更多相关文章
- Influx Sql系列教程九:query数据查询基本篇二
前面一篇介绍了influxdb中基本的查询操作,在结尾处提到了如果我们希望对查询的结果进行分组,排序,分页时,应该怎么操作,接下来我们看一下上面几个场景的支持 在开始本文之前,建议先阅读上篇博文: 1 ...
- 【SQL系列】深入浅出数据仓库中SQL性能优化之Hive篇
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[SQL系列]深入浅出数据仓库中SQL性能优化之 ...
- Influx Sql系列教程八:query数据查询基本篇
前面几篇介绍了InfluxDB的添加,删除修改数据,接下来进入查询篇,掌握一定的SQL知识对于理解本篇博文有更好的帮助,下面在介绍查询的基础操作的同时,也会给出InfluxSql与SQL之间的一些差别 ...
- 经典51道SQL查询练习题
数据表介绍 --1.学生表 Student(SId,Sname,Sage,Ssex) --SId 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 --2.课程表 Course( ...
- LINQ to SQL 系列 如何使用LINQ to SQL插入、修改、删除数据
http://www.cnblogs.com/yukaizhao/archive/2010/05/13/linq_to_sql_1.html LINQ和 LINQ to SQL 都已经不是一个新事物了 ...
- LINQ to SQL 系列 如何使用LINQ to SQL插入、修改、删除数据 (转)
http://www.cnblogs.com/yukaizhao/archive/2010/05/13/linq_to_sql_1.html LINQ和 LINQ to SQL 都已经不是一个新事物了 ...
- SQL Server性能优化(6)查询语句建议
1. 如果对数据不是工业级的访问(允许脏读),在select里添加 with(nolock) ID FROM Measure_heat WITH (nolock) 2. 限制结果集的数据量,如使用TO ...
- mysql:10道mysql查询语句面试题
表结构 学生表student(id,name) 课程表course(id,name) 学生课程表student_course(sid,cid,score) 创建表的sql代码 ```sql creat ...
- 10道mysql查询语句面试题
1.https://www.yanxurui.cc/posts/mysql/10-sql-interview-questions/ 2.http://mm.fancymore.com/reading/ ...
随机推荐
- C# MVC 返回html内容
var ss = Server.MapPath(""); //C:\Users\Administrator\Desktop\Csharp测试程序\TestMVC\TestMVC s ...
- phpstorm 使用
常用快捷 ctrl + / 单行注释 Alt+1 隐藏左侧任务栏 设置 1:control+shift+A功能可以搜索对应功能,把mouse:Change font size(Zoom) ...的按钮 ...
- MySQL基础命令小结
数据库授权登录[root@localhost ~]# mysql -uroot -p123456mysql> grant select,lock tables on auth.* to 'adm ...
- ListUtil集合操作常用方法类
* 集合操作常用方法类. * <p> * * @author 柯 */ public class ListUtil { /** * 判断List不为空,非空返回true,空则返回false ...
- Nginx服务器部署SSL证书手机不信任解决方法
在wosign申请证书并按指南正确部署证书后,如果发现PC浏览器访问正常,手机或safari浏览器提示证书不受信任,那肯定是在文件传输解压过程中导致证书文件中出现空格.乱码之类的情况,这里教您轻松四步 ...
- [置顶]
来自 Google 的高可用架构理念与实践
转自: https://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=402738153&idx=1&sn=af5e76aad ...
- HTML学习笔记之基本介绍
超文本标记语言 (Hyper Text Markup Language,HTML)不是一种编程语言,而是一种标记语言,用一套标记标签描述网页 HTML 标记标签又被称为 HTML 标签(HTML Ta ...
- Python中的sorted() 和 list.sort() 的用法总结
只要是可迭代对象都可以用sorted . sorted(itrearble, cmp=None, key=None, reverse=False) =号后面是默认值 默认是升序排序的, 如果想让结果降 ...
- Centos6.4建立本地yum源
https://jingyan.baidu.com/article/e9fb46e1aed8207521f7662c.html
- 基于I/O的Server/Client实现
在前面的文章中讲了基于NIO实现的Server/Client.本文就讲讲基于同步堵塞式I/O实现的Server/Client好与前面的NIO中的Server/Client进行对照. 网络编程中须要解决 ...