简介

最近在练习SQL基础,首先感叹一下,在机器上写和在纸上写还是有区别的。

本文的练习题目请点击此链接进行查看:http://www.cnblogs.com/edisonchou/p/3878135.html


提要:本文只列举个人认为有点难度,且有必须要重温知识点的题目,详细还请查看上面所给的链接进行练习。

练习题

(1)查询学过“001”并且也学过编号“002”课程的同学的学号、姓名;

  1. 思路1:使用++intersect++(intersect的使用)
  2. 思路1:使用++EXISTS++(EXISTS的用法)

--解法一:求交集
select s.S#,s.Sname
from Student s,SC sc
where s.S#=sc.S# and sc.C#='001'
intersect
select s.S#,s.Sname
from Student s,SC sc
where s.S#=sc.S# and sc.C#='002'
--解法二:使用exists
select s.S#,s.Sname
from Student s,SC sc
where s.S#=sc.S# and sc.C#='001' and exists
(
    select * from SC sc2 where sc.S#=sc2.S# and sc2.C#='002'
)

小知识:EXISTS与IN的使用效率的问题,通常情况下采用exists要比in效率高,因为IN不走索引,但要看实际情况具体使用:
IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

(7)查询学过“叶平”老师所教的所有课的同学的学号、姓名

分析:这题要注意一个老师可能教多门课

  1. 先在成绩单上查询到教师为“叶平”老师的信息,通过学生ID进行分组并获取考试门数
  2. 然后统计课程表上的“叶平”老师的课程数
    3.第一个条件的学生考试门数跟第二个条件的“叶平”老师所教课程数进行对比,相等即时答案

select s.S#,s.Sname 
from Student s
where s.S# in 
(
    select sc.S# 
    from SC sc,Course c,Teacher t
    where c.C#=sc.C# and c.T#=t.T# and t.Tname='叶平'
    group by sc.S#
    having COUNT(sc.C#)=
    (
        select COUNT(c1.C#) 
        from Course c1,Teacher t1 
        where c1.T#=t1.T# and t1.Tname='叶平'
    )
)

(14)查询和“002”号的同学学习的课程完全相同的其他同学学号和姓名

注意:查询的是跟“002”完全相同,且是其他,记得得排除“002”

  1. 首先确定学生课程范围在“002”学生所选的课程范围内;
  2. 然后就是对比他们间的课程数。

完成上面两个条件即可确定他们所选的所有课程是否都相等了

select s.S#,s.Sname 
from Student s
where s.S#!='002' and s.S# in 
(
    select distinct(S#) from SC
    where C# in (select C# from SC where S#='002')
    group by S#
    having COUNT(distinct C#)=
    (
        select COUNT(distinct C#) from SC
        where S#='002'
    )
)

(16)向SC表中插入一些记录,这些记录要求符合以下条件:①没有上过编号“002”课程的同学学号;②插入“002”号课程的平均成绩

  1. 先查询第一个条件的学员,因为插入的学号需要用到;
  2. 然后获取课程“002”的平均分,这里是获取分数用于插入;

最后答案就顺理成章了:

INSERT INTO dbo.Sc
SELECT s.S#,'002',(SELECT AVG(score) FROM dbo.Sc WHERE C#='002')
from  dbo.Student s
WHERE s.S# NOT IN(SELECT DISTINCT(sc.S#) FROM dbo.Sc sc WHERE sc.C#='002')

(17)按平均成绩从低到高显示所有学生的“语文”、“数学”、“英语”三门的课程成绩,按如下形式显示: 学生ID,语文,数学,英语,有效课程数,有效平均分

这里涉及到行转列的知识,在查询语数英这三列的时候用到了子查询和主查询的关联保证了与其他列数据的关联性

  1. 请各位要注意对分组(Group by)的概念较为清晰,重点就在学生的ID:S#
  2. 行转列知识:http://www.cnblogs.com/kerrycode/archive/2010/07/28/1786547.html

select t.S# as '学生ID',
(select Score from SC where S#=t.S# and C#='002') as '语文',
(select Score from SC where S#=t.S# and C#='003') as '数学',
(select Score from SC where S#=t.S# and C#='004') as '英语',
COUNT(t.C#) as '有效课程数',
AVG(t.Score) as '有效平均分'
from SC t
group by t.S#
order by AVG(t.Score)

(19)按各科平均成绩从低到高和及格率的百分数从高到低顺序

  1. CASE WHEN *** THEN *** ELSE *** END 的使用
  2. 及格率SUM(PassedCounts)/COUNT(AllCounts)的计算
  3. 另外,这里[Percent(%)]可以使用100 * SUM(CASE WHEN
    ISNULL(sc.Score,0)>=60 THEN 1 ELSE 0 END)/COUNT(*)替代。

 SELECT sc.C#,c.Cname,AVG(sc.score) AS avgScore,100*SUM(CASE WHEN ISNULL(score,0)>=60 THEN 1 ELSE 0 END )/COUNT(*) 
 FROM dbo.Sc sc,dbo.Course c
 WHERE sc.C#=c.C#
 GROUP BY sc.C#,c.Cname
 order BY AVG(sc.score)

(20)查询如下课程平均成绩和及格率的百分数(备注:需要在1行内显示): 企业管理(002),OO&UML (003),数据库(004)

这里也是涉及行转列的问题,由于列的数据都是相对独立的,也就没有关联子查询的的问题了

select 
SUM(CASE WHEN C#='002' THEN Score ELSE 0 END)/SUM(CASE C# WHEN '002' THEN 1 ELSE 0 END) as '企业管理平均分',
100 * SUM(CASE WHEN C#='002' and Score>=60 THEN 1 ELSE 0 END)/SUM(CASE C# WHEN '002' THEN 1 ELSE 0 END) as '企业管理及格百分比',
SUM(CASE WHEN C#='003' THEN Score ELSE 0 END)/SUM(CASE C# WHEN '003' THEN 1 ELSE 0 END) as 'OO&UML平均分',
100 * SUM(CASE WHEN C#='003' and Score>=60 THEN 1 ELSE 0 END)/SUM(CASE C# WHEN '003' THEN 1 ELSE 0 END) as 'OO&UML及格百分比',
SUM(CASE WHEN C#='004' THEN Score ELSE 0 END)/SUM(CASE C# WHEN '004' THEN 1 ELSE 0 END) as '数据库平均分',
100 * SUM(CASE WHEN C#='004' and Score>=60 THEN 1 ELSE 0 END)/SUM(CASE C# WHEN '004' THEN 1 ELSE 0 END) as '数据库及格百分比'
from SC

(24)查询学生平均成绩及其名次;

看似简单,名次这里其实不好弄。

  1. 首先使用group by获取需要的字段(学生ID,平均分)
  2. 然后这段sql需要再拿来新建并进行对比

select s.S#,s.Sname,T2.AvgScore,
    (select COUNT(AvgScore) from 
    (select S#,AVG(Score) as 'AvgScore' from SC group by S#) as T1 
    where T2.AvgScore<T1.AvgScore)+1 as 'Rank'
from 
    (select S#,AVG(Score) as 'AvgScore' from SC
    group by S#) as T2,
    Student s
where s.S#=T2.S#
order by AvgScore desc

(25)查询各科成绩前三名的记录:(不考虑成绩并列情况)

  1. 建立子查询获取每科前三名,这里需要跟主查询进行关联,而关联的字段就是科目字段C#
  2. 主查询难度不大,查询条件包括分数区域在子查询的分数区域内并且主和子查询的科目进行关联

select sc.C#,c.Cname,sc.S#,s.Sname,sc.Score 
from Student s,SC sc,Course c
where sc.C#=c.C# and sc.S#=s.S# and sc.Score in
(
    select top 3 Score from SC sc2
    where sc.C#=sc2.C#
    Order by Score desc
)
order by sc.C#,sc.Score desc

以上就是我用纸张手写的时候遇到有难度的题目,希望能给各位一些参考。

相关文章