50道SQL练习题

用了一些不同的写法,有的存在bug,在注释中标注了。

很多写法都是重复的,只是为了练手,看哪种写法更便于阅读和提高查询效率

--查询" 01 “课程比” 02 "课程成绩高的学生的信息及课程分数
---------------------------------------------------------with子查询
with
	A as (select SId,score from SC where CId='01'),
	B as (select SId,score from SC where CId='02')
select * 
from Student 
where SId in (
			   select A.SId from A,B 
			   where A.score > B.score 
				 and A.SId  =B.SId 
			  )
------------------------------------------------------------直接查询(笛卡尔积)
select * from Student where SId in
(select B.SId from 
	(select SId,score from SC where CId='01')A,
	(select SId,score from SC where CId='02')B
where A.SId =B.SId and A.score>B.score 
)
-------------------------------------------------------------inner join查询
select * from Student where SId in(
select S1.SId from 
(select SId,score from SC where CId='01')S1
inner join 
(select SId,score from SC where CId='02')S2
on S1.SId =S2.SId 
where S1.score >S2.score )
-------------------------------------------------
select Student.Sname,c.score01,score02
from Student INNER JOIN
(SELECT a.Sid,a.score score01,b.score score02
FROM (SELECT Sid,score FROM sc WHERE cid='01') a ,
	(SELECT sid,score FROM SC where cid='02') b
WHERE a.Sid=b.SId AND a.score>b.score) c
ON Student.sid=c.Sid


GO


--查询同时存在"01"课程和"02"课程的情况
-------------------------------------------------------------inner join查询
select * from Student where SId in(
select S1.SId from 
(select SId from SC where CId='01')S1
inner join 
(select SId from SC where CId='02')S2
on S1.SId =S2.SId 
 )
---------------------------------------------------------with as子查询
with
	A as (select SId from SC where CId='01'),
	B as (select SId from SC where CId='02')
select SId from Student where SId in 
(	select A.SId from A,B where A.SId=B.SId 
)
--------------------------------------------------------直接查询,就是笛卡尔积查询
select * from Student where SId in
(select S1.SId from 
	(select SId from SC where CId='01')S1,
	(select SId from SC where CId='02')S2
	where S1.SId = S2.SId)

go


--查询存在"01"课程但可能不存在"02"课程的情况(不存在时显示为null)
--------------------------------------------------------------left join,只查询学号和成绩
	select S1.SId 学号,
		   S1.score 课程01,
		   S2.score 课程02
	from 
	(select SId,score from SC where CId='01')S1 
	left join
	(select SId,score from SC where CId='02')S2
	on S1.SId =s2.SId 

------------------------------------------------------------多个join连用,按先后顺序连接
select S.SId 学号,
	   Sname 姓名,
	   Ssex 性别,
	   S1.score 成绩1,
	   S2.score 成绩2
from Student S
right join
(select SId,score from SC where CId='01')S1 on S.SId = s1.SId 
left join
(select SId,score from SC where CId='02')S2 on S.SId = s2.SId 
--------------------------------------------------------------------错误写法!!!直接查询,类似于inner join
select S.SId 学号,
	   S.Sname 姓名,
	   S1.score 成绩01,
	   S2.score 成绩02
from   Student S,
	  (select SId,score from SC where CId='01')S1,
	  (select SId,score from SC where CId='02')S2
where  S.SId = S1.SId 
   and S.SId = S2.SId 

go


--查询不存在"01"课程但存在"02"课程的情况
-------------------------------------------------------------------用in进行查询
select * from Student 
where SId not in
			(select SId from SC where CId='01')
 and  SId in 
			(select SId from SC where CId='02')

-------------------------------------------------------------------用except查询
with
	A as (select SId from SC where CId='01'),
	B as (select SId from SC where CId='02')
select * from Student
where SId in
		(
			select SId from B 
			except 
			select SId from A
		)
--------------------------------------------------------------------先join再where ,使用all
with
	A as (select SId from SC where CId='01'),
	B as (select SId from SC where CId='02')
select * 
from Student S
	 right join B on B.SId = S.SId 
where S.SId <> all(select * from A)
go


--查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
--------------------------------------------------------------------------------用with as
with 
	A as (select SId,AVG(score) 平均值 from SC group by SId having AVG(score)>=60)
select S.SId 学生编号,
	   S.Sname 学生姓名,
	   A.平均值
from   Student S,A
where  S.SId =A.SId 
----------------------------------------------------------------------------------不用with
select S.SId 学生编号,
	   S.Sname 学生姓名,
	   A.平均值
from   Student S,
	  (select SId,AVG(score) 平均值 from SC group by SId having AVG(score)>=60)A
where  S.SId =A.SId 
----------------------------------------------------------------------------------left join
select *
from
(select s.Sid,s.Sname ,avg(score) avgscore
from Student S left join SC S2 on S.Sid = S2.SId
group by s.Sid, s.Sname) a ---SId相同的,Sname也相同,但是这样写,可以让两者都能在select的结果中显示
where a.avgscore>60
go



--查询在 SC 表存在成绩的学生信息
--------------------------------------------------------------------------------- in 
select * from Student 
where SId in 
			(select distinct SId from SC)
---------------------------------------------------------------------------------any
select * from Student 
where SId = 
			any(select SId from SC)
go


--查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )
-------------------------------------------------------------------------------------------left join + with + group by 
with
	A as (select SId,SUM(score) 总成绩,COUNT(CId)选课总数 from SC group by SId)
select S.SId 学生编号,
	   S.Sname 学生姓名,
	   A.选课总数,
	   A.总成绩 
from   Student S
  left join A on A.SId = S.SId 
---------------------------------------------------------------------------------------先join,再group by
select S.SId ,S.Sname ,COUNT(score) 选课总数,sum(score)总成绩
from   Student S
	left join SC C on S.SId=C.SId 
group by S.SId ,S.Sname 
go



--查有成绩的学生信息
------------------------------------------------------------------------------in
select * 
from 
	Student
where SId in
		(select distinct SId from SC) 
------------------------------------------------------------------------any
select * from Student 
where SId = 
			any (select SId from SC)
-------------------------------------------------------------------join,提高查询效率
select * 
from Student S
inner join SC C on S.SId =C.SId 
GO



--查询「李」姓老师的数量
------------------------------------------------------------------------like
select COUNT(TId)
from Teacher
where Tname like '李%'
go



--查询学过「张三」老师授课的同学的信息
---------------------------------------------------------------------------with套用
with
	A as (select TId from Teacher where Tname='张三'),
	B as (select CId from Course,A where A.TId = Course.TId),
	C as (select SId from SC,B where SC.CId = B.CId )
select S.SId 学号,
	   S.Sname 姓名,
	   S.Sage 年龄,
	   S.Ssex 性别
from Student S,C where C.SId =S.SId 
-----------------------------------------------------------------------多个select嵌套+in
select SId from SC where CId in (
	select CId from Course where TId =
		(select TId from Teacher where Tname='张三'))
go



--查询没有学全所有课程的同学的信息
----------------------------------------------------------------------not in + group by 
select * from Student 
where SId not in 
	(select SId from SC group by SId having COUNT(CId)=(select COUNT(CId) from Course))
	
----------------------------------------------------------------------all
select * from Student  
where SId<>
			all(select SId from SC group by SId having COUNT(CId)=(select COUNT(CId) from Course))
------------------------------------------------------------------------declare + except
declare @i int
set @i=(select COUNT(distinct CId) from Course);
with 
	A as (select SId from Student),
	B as (select SId from SC group by SId having COUNT(CId)=@i)
select * from Student 
where SId in
(	select * from A
	except
	select * from B
)
go



--查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息
--------------------------------------------------------------------------------in
select * from Student 
where SId in
	(select SId from SC where CId in
		(select CId from SC where SId='01')
	)
-----------------------------------------------------------------------------any
select * from Student 
where SId in
	(select SId from SC where CId = any
		(select CId from SC where SId='01')
	)
---------------------------------------------------------------------------with 
with
	A as (select CId from SC where SId = '01'),
	B as (select SId from SC where CId = any (select * from A))
select * from Student 
where SId in (select * from B)

go



--查询和" 01 "号的同学学习的课程 完全相同的其他同学的信息
-----------------------------------------------------------------------not in
with 
	A as (select CId from SC where SId='01'),
	B as (select COUNT(CId) num from SC where SId='01')
select * 
from   Student 
where  SId not in(select SId from SC where CId not in (select * from A ))  -----排除选课和01不同的学生
   and SId in(select SId from SC group by SId having COUNT(CId)=(select * from B))  ----选择和01选课数相同的学生
   and SId <>'01'  ----排除01
-------------------------------------------------------------------------连接+exists
with
	A as (select SId,CId from Student ,(select CId from SC where SId='01')a),
	B as (select A.SId 学号,isnull(c.SId ,0)选课 from A left join SC c on A.CId =c.CId and A.SId =c.SId ),
	C as (select distinct 学号 from B where 选课='0')
select * from Student S where not exists(select 1 from C where C.学号 =S.SId ) and SId <>'01'
go




--查询没学过"张三"老师讲授的任一门课程的学生姓名
-----------------------------------------------------------------------------------in+not in
with
	A as (select TId from Teacher where Tname='张三'),  --张三老师教师号
	B as (select CId from Course,A where Course.TId = A.TId ), ---张三老师教的课
	C as (select SId from SC where CId in (select * from B))--学过张三老师课的学生编号
	
select SId,Sname from Student where SId <>all
 (select * from C)
 go
--------------------------------------------------------------------------------left join
with
	A as (select TId from Teacher where Tname='张三'),  --张三老师教师号
	B as (select CId from Course,A where Course.TId = A.TId ), ---张三老师教的课
	C as (select SId,score from SC where CId = (select * from B)) ---上过张三老师课的学生以及成绩
select S.SId,S.Sname
from   Student S
	left join  C on C.SId =S.SId  --左连接
where score is null

go



--查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
---------------------------------------------------------------------笛卡尔积 + group by 
with
	A as (select SId,AVG(score)平均成绩 from SC where score<60 group by SId having COUNT(score)>=2)
select S.SId 学号,	
	   S.Sname 姓名,
	   A.平均成绩 
from   Student S, A
where  S.SId = A.SId 
--------------------------------------------------------------------------------inner join
with
	A as (select SId,AVG(score)平均成绩 from SC where score<60 group by SId having COUNT(score)>=2)
select S.SId,S.Sname,A.平均成绩 
from Student s
inner join A on A.SId=s.SId  
--------------------------------------------------------------------------------join + group by
select S.SId ,Sname,AVG(score) 平均成绩
from Student S
inner join SC C on S.SId =C.SId 
where C.score <60
group by S.SId ,S.Sname 
having COUNT(*)>=2
go



--检索" 01 "课程分数小于 60,按分数降序排列的学生信息
------------------------------------------------------------------------笛卡尔积
select s.SId,S.Sname,S.Ssex,score 
from Student S,SC
where SC.SId =S.SId and CId='01' and score<60
order by score DESC
go
---------------------------------------------------------------------------join
with
	A as (select SId,score from SC where CId='01' and score<60)
select s.SId ,S.Sname ,S.Ssex,A.score 
from Student S
inner join A 
on A.SId =S.SId 
order by A.score DESC
go




--按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
-----------------------------------------------------------------------------left join + order by
with 
	A as (select SId,AVG(score)avgscore from SC group by SId),
	B as (select S.*,CId,score from Student S left join SC C on S.SId =C.SId )
select B.SId ,B.Sname ,B.CId ,B.score ,A.avgscore
from B left join A on A.SId =B.SId 
order by avgscore desc

GO





--查询各科成绩最高分、最低分和平均分:
--以如下形式显示:课程 ID,课程 name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
--及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
--要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
-------------------------------------------------------------------------------------------------
with
	A as (select CId,AVG(score)平均分,MAX(score)最高分,MIN(score)最低分,COUNT(score)总数 from SC group by CId),
	A1 as (select CId,COUNT(score)及格数 from SC where score>=60 group by CId ),
	A2 as (select CId,COUNT(score)中等数 from SC where score>=70 and score<80 group by CId),
	A3 as (select CId,COUNT(score)优良数 from SC where score>=80 and score<90 group by CId),
	A4 as (select CId,COUNT(score)优秀数 from SC where score>=90 group by CId),
	AAA as (select A.CId ,A.平均分 ,A.总数 ,isnull(A1.及格数,0)及格数 ,isnull(A2.中等数,0)中等数 ,isnull(A3.优良数,0) 优良数,isnull(A4.优秀数 ,0)优秀数,A.最低分 ,A.最高分 
			from A
				left join A1 on A1.CId = A.CId 
				left join A2 on A2.CId = A.CId 
				left join A3 on A3.CId = A.CId
				left join A4 on A4.CId = A.CId)
--select * from AAA
--select 及格数/总数 from AAA
select AAA.CId 课程ID,
       Course.Cname 课程名,
	   AAA.平均分,
	   AAA.最高分,
	   AAA.最低分,
	   AAA.总数 选修人数,
	   cast(ROUND(cast(及格数 as float)/总数,2)*100 as varchar(10))+'%' 及格率,
	   cast(ROUND(cast(中等数 as float)/总数,2)*100 as varchar(10))+'%' 中等率,
	   cast(ROUND(cast(优良数 as float)/总数,2)*100 as varchar(10))+'%' 优良率,
	   cast(ROUND(cast(优秀数 as float)/总数,2)*100 as varchar(10))+'%' 优秀率
from AAA,Course 
where AAA.CId = Course.CId 
order by AAA.总数 DESC, AAA.CId ASC
---------------------------------------------------------------------------------------------------------group by + case when 
with
	A as (select CId,AVG(score)平均分,MAX(score)最高分,MIN(score)最低分,COUNT(score)总数,
		  CONVERT(varchar,CONVERT(decimal(18,1),100*sum(case when score>=60 then 1 else 0 end)/COUNT(*)))+'%' as 及格率,
	      CONVERT(varchar,CONVERT(decimal(18,1),sum(case when score>=70 and score<80 then 1 else 0 end)*100/COUNT(*)))+'%' as 中等率,
		  CONVERT(varchar,CONVERT(decimal(18,1),sum(case when score>=80 and score<90 then 1 else 0 end)*100/count(*)))+'%' as 优良率,
		  CONVERT(varchar,CONVERT(decimal(18,1),sum(case when score>=90 then 1 else 0 end)*100/count(*)))+'%' as 优秀率
		  from SC group by CId)
select Cname,A.* from Course ,A
where A.CId = Course .CId 
order by A.总数 desc,A.CId asc
go




--按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺
------------------------------------------------------------------------------------------------找到SC表内,所有比本条数据分数大的分数n条,那么这条序号就是n+1
select CId 课程号,
	   SId 学号,
	   (select COUNT(*) from SC where score>a.score and CId=a.CId )+1 rank 
from   SC a
order by CId,rank
-------------------------------------------------------------------------------------------------左连接,条件:课程号相同,且比本人分数高,分组计数
select a.cid 课程号, 
	   a.sid 学号, 
	   count(b.score)+1 as rank
from   sc as a
	left join sc as b on a.score<b.score and a.cid = b.cid
group by a.cid, a.sid,a.score
order by a.cid, rank ASC;
------------------------------------------------------------------------------------------rank:会把重复的排名一样
select CId 课程号,
	   SId 学号,
	   RANK() over(partition by CId order by score desc) as 排名
from   SC 
order by CId,排名

 
go




--按各科成绩进行排序,并显示排名, Score 重复时合并名次
---------------------------------------------------------------------------------------------找到SC表中,比本条分数大的所有不一样的分数n条,那么这条序号就是n+1
select CId 课程号,
	   SId 学号,
	  (select COUNT(distinct score) from SC where CId=t.CId and t.score>score )+1 rank
from   SC t
order by 
     CId,
     rank
----------------------------------------------------------------------------------------------dense_rank()函数
select CId 课程号,
	   SId 学号,
	   dense_RANK() over(partition by CId order by score desc) as 排名
from   SC 
order by CId,排名
-----------------------------------------------------------------------------------SC表左连接,计算比自己分数高的分数个数,只计算不同的分数,重复的不计入内
select a.cid 课程号, 
	   a.sid 学号, 
	   count(distinct b.score)+1 as rank
from   sc as a
	left join sc as b on a.score<b.score and a.cid = b.cid
group by a.cid, a.sid,a.score 
order by a.cid, rank ASC; 

go



--查询学生的总成绩,并进行排名,总分重复时保留名次空缺
------------------------------------------------------------------------------count()函数
with
	A as (select SId,SUM(score)总分 from SC group by SId)
select SId,
       总分,
       (select COUNT(总分) from A where 总分>t.总分)+1 rank
from A t
order by rank
go
-------------------------------------------------------------------------------left join
with
	A as (select SId,SUM(score)总分 from SC group by SId)
select A.SId 学号,
	   A.总分 ,
	   COUNT(B.总分)+1 排名
from A left join A B on A.总分<B.总分  
group by A.SId ,A.总分 
order by A.总分 desc
go
-----------------------------------------------------------------------------rank
with
	A as (select SId,SUM(score)总分 from SC group by SId)
select A.*,RANK() over(order by 总分 desc)as rank from A order by rank 
go



--查询学生的总成绩,并进行排名,总分重复时不保留名次空缺
-----------------------------------------------------------------------------count
with
	A as (select SId,SUM(score)总分 from SC group by SId)
select SId,
       总分,
       (select COUNT(distinct 总分) from A where 总分>t.总分)+1 rank
from A t
order by rank
--------------------------------------------------------------------------------dense_rank
with
	A as (select SId,SUM(score)总分 from SC group by SId)
select A.*,
	   DENSE_RANK() over(order by 总分 desc) rank
from A order by rank
----------------------------------------------------------------------------------join
with
	A as (select SId,SUM(score)总分 from SC group by SId)
select A.*,COUNT(distinct B.总分)+1 as rank
from A left join A B on A.总分<B.总分 
group by A.SId ,A.总分 
order by rank
go



--统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比
go
with
	A as (select CId ,count(score)总数 from SC group by CId),
	A1 as (select CId,COUNT(score)不及格数 from SC where score<60 group by CId ),
	A2 as (select CId,COUNT(score)及格数 from SC where score>=60 and score<70 group by CId ),
	A3 as (select CId,COUNT(score)中等数 from SC where score>=70 and score<85 group by CId),
	A4 as (select CId,COUNT(score)优秀数 from SC where score>=85 and score<100 group by CId),
	AAA as (select A.CId ,A.总数 ,isnull(A1.不及格数,0)不及格数 ,isnull(A2.及格数,0)及格数 ,isnull(A3.中等数,0) 中等数,isnull(A4.优秀数 ,0)优秀数 
			from A
				left join A1 on A1.CId = A.CId 
				left join A2 on A2.CId = A.CId 
				left join A3 on A3.CId = A.CId
				left join A4 on A4.CId = A.CId)
select AAA.CId 课程编号,
       Course.Cname 课程名称,
       AAA.不及格数 [60-0] ,
	   cast(ROUND(cast(不及格数 as float)/总数,2)*100 as varchar(10))+'%' [占比],
	   AAA.及格数 [60-70] ,
	   cast(ROUND(cast(及格数 as float)/总数,2)*100 as varchar(10))+'%' [占比],
	   AAA.中等数 [70-85],
	   cast(ROUND(cast(中等数 as float)/总数,2)*100 as varchar(10))+'%' [占比],
	   AAA.优秀数 [85-100],
	   cast(ROUND(cast(优秀数 as float)/总数,2)*100 as varchar(10))+'%' [占比],
	   AAA.总数 选课总人数
from AAA,Course
where AAA.CId = Course.CId 
order by AAA.总数 DESC, AAA.CId ASC
go
------------------------------------------------------------------------------------------------convert
select SC.CId,Cname,
	   sum(case when score<60 then 1 else 0 end) as 人数,
	   convert(varchar,CONVERT(decimal(18,1),sum(case when score<60 then 1 else 0 end)*100/COUNT(*)))+'%' as [0-60],
	   sum(case when score>=60 and score<70 then 1 else 0 end) as 人数,
	   convert(varchar,CONVERT(decimal(18,1),sum(case when score>=60 and score<70 then 1 else 0 end)*100/COUNT(*)))+'%' as [60-70],
	   sum(case when score>=70 and score<85 then 1 else 0 end) as 人数,
	   convert(varchar,CONVERT(decimal(18,1),sum(case when score>=70 and score<85 then 1 else 0 end)*100/COUNT(*)))+'%' as [70-85],
	   sum(case when score>=85  then 1 else 0 end) as 人数,
	   convert(varchar,CONVERT(decimal(18,1),sum(case when score>=85 then 1 else 0 end)*100/COUNT(*)))+'%' as [85以上]
from SC,Course where SC.CId =Course.CId 
group by SC.CId,Cname
order by SC.CId 
go








--查询各科成绩前三名的记录
-------------------------------------------------------------------------------------------------row_number+partition
with 
	A as (select *,ROW_NUMBER() over(partition by CId order by score desc) as num from SC )
select * from A where num<=3
order by CId,score desc
-----------------------------------------------------------------------------------------------查询效率最低
select a.CId ,a.SId ,a.score 
from SC a 
where a.SId in(select top 3 SId
				from SC b
				where a.CId =b.CId 
				order by score desc
				)
order by CId,score desc
------------------------------------------------------------------------------------------------------------成绩重复的情况下,会出现bug,比如99,88,88,88,88,77
select * from SC a
where (select count(*) from SC b where a.CId =b.CId and b.score>a.score)<3
order by CId,score desc

go



--查询每门课程被选修的学生数
select CId ,COUNT(SId) from SC group by CId

go



--查询出只选修两门课程的学生学号和姓名
-----------------------------------------------------------in 判断
select Sname 姓名,
	   SId 学号
from Student 
where SId in
(select SId from SC group by SId having COUNT(CId)=2)
--------------------------------------------------------------join 连接
select S.Sname,S.SId
from Student S
inner join SC on SC.SId =S.SId 
group by Sname,S.SId
having COUNT(CId)=2
go



--查询男生、女生人数

select Ssex,COUNT(Ssex)
from Student 
GROUP BY Ssex

go



--查询名字中含有「风」字的学生信息
select * from Student where Sname like '%风%'

go



--查询同名同性学生名单,并统计同名人数
----------------------------------------------------------------------先with子查询,再对临时表进行分组
with
	A as (select SId,Sname,Ssex from Student t where Sname = any (select Sname from Student where Sname=t.Sname and t.Ssex= Ssex and SId!=t.SId )),
	B as (select Sname,COUNT(Sname)人数 from A group by Sname)

select A.* ,B.人数  from A join B on A.Sname =B.Sname order by A.Sname
------------------------------------------------------------------------group by 两个字段 + 笛卡尔积
select S.*,C.num
from Student S,
	(select Sname,Ssex,COUNT(Sname) num from Student group by Sname,Ssex)C
where S.Sname =C.Sname and C.num >1
-----------------------------------------------------------------------------group by 两个字段 + exists
select * from Student a
where exists(
			select Sname ,COUNT(*)
			from Student b 
			where b.Sname =a.Sname 
			group by Sname ,Ssex
			having COUNT(*)>1
			)
go



--查询 1990 年出生的学生名单
--------------------------------------------------------------------通过范围查找
select * from Student where Sage >= '1990' and Sage<'1991'
----------------------------------------------------------------------通过datepart查找
select * from Student where DATEPART(YY,Sage)='1990'
go



--查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select CId,
	   AVG(score)平均成绩 
from SC 
group by CId 
order by 平均成绩 desc,
	     CId 
go




--查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩
-------------------------------------------------------------------------------------------inner join
select S.SId,Sname,C.平均成绩 
from Student S
inner join
(select SId,AVG(score)平均成绩 from SC group by SId having AVG(score)>=85)C
on S.SId =C.SId 
go
--------------------------------------------------------------------------------------------笛卡尔积
with
	A as (select SId,AVG(score)平均成绩 from SC group by SId having AVG(score)>=85)
select Student.Sname,Student.SId ,A.平均成绩 
from Student ,A
where Student.SId =A.SId 

go



--查询课程名称为「数学」,且分数低于 60 的学生姓名和分数
------------------------------------------------------------------------------------------with
with
	A as (select CId from Course where Cname='数学'),
	B as (select SId,score from SC where CId in (select * from A) and score <60)
select Sname,B.score
from Student ,B
where Student.SId =B.SId 

go



--查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)
----------------------------------------------------------------------------------------------left join
select a.Sname ,c.Cname ,b.score 
from Student a
left join SC b on a.SId =b.SId 
left join Course c on c.CId = b.CId 
order by c.CId  desc
go
------------------------------------------------------------------------------------------------------with left join
with
	A as (select Student.SId,Sname,CId,Cname  from Student ,Course),
	B as (select A.* ,SC.score from A left join SC on SC.CId = A.CId and SC.SId =A.SId )
select * from B
-----------------------------------------------------------------------------------------------------left join
select b.Sname,Course.Cname,b.score
from
(select a.SId,a.Sname,sc.cid,sc.score
from 
(select sid,Sname,cid
from Student,Course) a left join sc
    on a.sid=sc.sid and a.cid=sc.cid) b left join Course on b.cid=Course.cid




--查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数
------------------------------------------------------------------------------------只要有70分,都算上
with
	A as (select * from SC where score>70),
	B as (select A.*,Course.Cname from A left join Course on A.CId =Course.CId),
	C as (select S.Sname,B.Cname,B.score from B left join Student S on B.SId=S.SId)
select * from C
-----------------------------------------------------------------------------------------最低分也有70分,left join,笛卡尔积
go
with
	A as (select SId from SC group by SId having MIN(score)>70),
	B as (select SC.* from SC inner join A on SC.SId = A.SId),
	C as (select S.Sname,Co.Cname ,B.score from B,Student S,Course Co where S.SId =B.SId and B.CId = Co.CId)
select * from C
----------------------------------------------------------------------------------------笛卡尔积
select s.Sname,c.Cname,sc.score
from Student s,Course c,SC
where s.SId=sc.SId and c.CId=sc.CId
    and sc.score>=70
go



--查询不及格的课程
with
	A as (select CId,score from SC where score<60),
	B as (select C.Cname,A.score from A,Course C where A.CId =C.CId)
select * from B
order by B.Cname 
go

select DISTINCT Course.Cname
from SC,Course
where sc.CId=Course.CId and sc.score<60



--查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名
with
	A as (select SId from SC where CId='01' and score>80)
select SId,Sname 
from Student 
where SId in
(select * from A)
go



--求每门课程的学生人数
select CId,COUNT(SId) from SC group by CId
go



--成绩不重复,查询选修「李四」老师所授课程的学生中,成绩最高的学生信息及其成绩(排除重复成绩)
----------------------------------------------------------------------------------------------------正确的
with
	A as (select TId from Teacher where Tname='李四'),--李四的教师号
	B as (select CId from Course where TId in (select * from A)), --01课程
	C as (select SId ,score from SC where CId = (select CId from B)), --01课程成绩表
	E as (select t.SId  from C t left join C p on t.score =p.score group by t.SId having COUNT(*)=1) ,--排除课程表重复选项
	F as (select top 1*from C where exists(select SId from E where E.SId =C.SId ) order by score desc)
select * from Student ,F where Student.SId = F.SId  

-----------------------------------------------------------------笛卡尔积计算无重复最高分
with 
	A as(select top 1 score
		 from   SC,Course,Teacher 
		 where  SC.CId =Course.CId 
		    and Course.TId = Teacher.TId 
		    and Teacher.Tname='李四'
		 group by score
		 having COUNT(*)=1
		 order by score desc
	)
select * from A
go



 
--成绩有重复的情况下,查询选修「李四」老师所授课程的学生中,成绩最高的学生信息及其成绩
-------------------------------------------------------------------------------------------------------------
with
	A as (select CId from Course where TId in (select TId from Teacher where Tname='李四')),--李四老师的课程
	B as (select MAX(score)最高分 from SC where CId in (select * from A)),--李四老师课程的最高分
	D as (select SId from SC where score in (select * from B) and CId in (select * from A)) --最高分的学号
select S.* ,
	   C.score 
from   Student S,SC C
where  S.SId = C.SId 
   and C.SId in (select * from D)
   and C.CId in (select * from A)
go
----------------------------------------------------------------------------------------更直观,易于读
SELECT s.*,
	   sc.score
FROM   Student s,
       Course c,
       Teacher t,
       SC 
WHERE  s.SId= sc.SId 
   and c.CId= sc.CId 
   and t.TId= c.TId and t.Tname='李四'
   and sc.score=(select MAX(score)
				 from   Student s,
					    Course c,
					    Teacher t,
					    SC 
				 where  s.SId= sc.SId 
					and c.CId= sc.CId 
					and t.TId= c.TId 
					and t.Tname='李四')
--------------------------------------------------------------------------------------------------rank/dense_rank + partition
go
with
	A as (select TId from Teacher where Tname='李四'),
	B as (select CId from Course where TId in (select * from A)),
	C as (select *,RANK() over(partition by CId order by score desc) as num from SC)
select S.*,C.score  
from Student S,C
where C.num =1 and C.CId in (select * from B) and S.SId =C.SId 
go






--查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩
-----------------------------------------------------------------------------A同学有两门课程相等
with
	A as(select score,SId from SC group by score,SId having COUNT(CId)>1 )
select * from SC ,A
where SC.SId = A.SId 
  and SC.score = A.score 
------------------------------------------------------------------------------SC表自连接
select * from SC
where SId in
	(select a.SId from SC a 
	inner join SC b on a.CId <>b.CId and a.SId =b.SId and a.score =b.score)

go



--查询每门功课成绩最好的前两名
------------------------------------------------------------------------------------------row_number over(partition)
select CId,SId,score
from (select *,ROW_NUMBER() over(partition by CId order by score desc) as number from SC)a
where number<=2
order by CId,score desc
--------------------------------------------------------------------------------------------嵌套查询,复杂度高
select CId,
       SId,
       score 
from   SC a
where SId in(select top 2 SId
			 from   SC b
			 where  a.CId =b.CId 
			 order by b.score 
			)
order by CId,score desc
-----------------------------------------------------------------------------------------利用比第一名第二名,成绩高的不超过两个,原理查询,存在bug:成绩重复,就会吧把所有的重复项都选上
select CId,SId,score from SC a
where (select COUNT(*) from SC b where a.CId =b.CId and b.score >a.score)<2
order by CId,score desc
go




--统计每门课程的学生选修人数(超过 5 人的课程才统计)
----------------------------------------------------------------------------group by
select SC.CId,
	   COUNT(SId)number,
	   Cname 
from   SC ,Course 
where  SC.CId = Course.CId 
group by SC.CId ,Cname
having COUNT(SId)>5





--检索至少选修两门课程的学生学号
select SId from SC group by SId having COUNT(CId)>=2
go




--查询选修了全部课程的学生信息
--------------------------------------------------------------------with
with
	A as (select COUNT(distinct CId)num from Course),
	B as (select SId from SC group by SId having COUNT(CId) in (select * from A))
 select * from Student 
 where SId in 
 (select * from B)
 ------------------------------------------------------------------------笛卡尔积
go
select Sname
from   sc,Student
where  sc.SId=Student.SId
group by Sname
having count(*)=(select count(*) from Course)



--查询各学生的年龄,只按年份来算
select SId,Sname,datediff(YY,Sage,GETDATE()) from Student 
go



--按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
----------------------------------------------------------------------------
with
	A as (select datepart(mm,GETDATE())月,DATEPART(DAY,GETDATE())日),
    B as (select S.SId,Sname,datediff(YY,Sage,GETDATE())-1 年龄 
         from Student S,A
         where datepart(mm,Sage)<A.月
            or (datepart(mm,Sage)=A.月 and datepart(dd,Sage)<A.日)),        
    C as (select SId,Sname,datediff(YY,Sage,GETDATE()) 年龄
          from Student
          where SId not in
	                (select SId from B))
select * from B
union all 
select * from C
order by SId
----------------------------------------------------------------------------
SELECT
    SId 学号,
    Sname 姓名,
    CASE WHEN MONTH(Sage) < MONTH(GETDATE()) OR MONTH(Sage) = MONTH(GETDATE()) AND DAY(Sage) < DAY(GETDATE())
		 THEN YEAR(GETDATE()) - YEAR(Sage)-1
		 ELSE YEAR(GETDATE()) - YEAR(Sage)
    END AS 年龄
FROM
    Student
----------------------------------------------------------------------------


go



--查询本周过生日的学生
select Sname from Student where DATEPART(WEEK,Sage)=DATEPART(week,GETDATE())

go



--查询下周过生日的学生
select Sname from Student where DATEPART(WEEK,Sage)=DATEPART(week,GETDATE())+1

go



--查询本月过生日的学生
select Sname from Student where DATEPART(mm,Sage)=DATEPART(mm,GETDATE())
select Sname from Student where MONTH(Sage) = MONTH(GETDATE())
go



--查询下月过生日的学生
select a.Sname
from   (
select sid,Sname,
    CASE WHEN DATEPART(month, GETDATE())=12 THEN 1
    ELSE DATEPART(month, GETDATE())+1
    END as nextMonth,DATEPART(month, Sage) birthday
    from Student) a
where a.birthday=a.nextMonth

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值