SQL总结(七)查询实战

一、场景

给定一个场景,学生选课系统为例,大家很熟悉。

主要关系:

学生(学号、姓名、年龄、性别)

教师(教师ID,教师姓名)

课程(课程ID,课程名称,任教教师ID)

成绩(学生ID,课程ID,成绩)

二、创建表并预置数据

创建关系表:

--学生:Student(SID,SName,SAge,SSex)
--学生表(学号、姓名、年龄、性别)
--性别,0表示男,1表示女
--
--IF EXISTS(SELECT OBJECT_ID('Student')) /*此处永远为true,原因是OBJECT_ID返回具体ID,或者NULL*/
--使用下列语句,如果没有,什么都不返回,也就不存在
IF EXISTS(SELECT id FROM sysobjects WHERE name='Student')
DROP Table Student Create table Student
(
SID nvarchar(20) primary key not null,
SName nvarchar(20),
SAge int,
SSex bit
) --教师:Teacher(TID,TName)
--教师表(教师ID,教师姓名)
IF EXISTS(SELECT id FROM sysobjects WHERE name='Teacher')
Drop table Teacher
GO Create table Teacher
(
TID nvarchar(20) primary key not null,
TName nvarchar(20) not null,
) --课程:Course(CID,CName,TID)
--课程表(课程ID,课程名称,任教教师ID)
IF EXISTS(SELECT id FROM sysobjects WHERE name='Course')
BEGIN
DROP Table Course
END
Create table Course
(
CID nvarchar(20) primary key not null,
CName nvarchar(50) not null,
TID nvarchar(20)
) IF EXISTS(SELECT id FROM sysobjects WHERE name='SC')
DROP TABLE SC --成绩:SC(SID,CID,Score)
--成绩表(学生ID,课程ID,成绩)
Create table SC
(
SID nvarchar(20) not null,
CID nvarchar(20) not null,
Score int
)
alter table SC add constraint PK_SC primary key(SID,CID)

预置数据

这里仅仅是个例子,针对不同的题目,可以预置适当的数据进行检测。

/*预置数据*/
DELETE FROM Student
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S001','Tom','','')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S002','Lucy','','')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S003','Jim','','')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S004','Brush','','')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S005','Kim','','')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S006','Fka','','')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S007','Cidy','','')
INSERT INTO Student(SID,SName,SAge,SSex) VALUES('S008','YouNi','','')
GO DELETE FROM Teacher
INSERT INTO Teacher(TID,TName) VALUES('T001','张三')
INSERT INTO Teacher(TID,TName) VALUES('T002','李四')
INSERT INTO Teacher(TID,TName) VALUES('T003','王五')
GO DELETE FROM Course
INSERT INTO Course(CID,CName,TID) VALUES('C01','英语','T001')
INSERT INTO Course(CID,CName,TID) VALUES('C02','体育','T002')
INSERT INTO Course(CID,CName,TID) VALUES('C03','数学','T003')
GO DELETE FROM SC
INSERT INTO SC(SID,CID,Score) VALUES('S001','C01','')
INSERT INTO SC(SID,CID,Score) VALUES('S001','C02','')
INSERT INTO SC(SID,CID,Score) VALUES('S001','C03','')
INSERT INTO SC(SID,CID,Score) VALUES('S002','C01','')
INSERT INTO SC(SID,CID,Score) VALUES('S003','C01','')
INSERT INTO SC(SID,CID,Score) VALUES('S004','C01','')
GO

三、具体题目

以下题目,希望是一种练习题,是对具体SQL查询方法的具体应用。对于一些复杂查询,也进行分步求解,希望不只是明白了一道题的解法,培养一种解题思路。

以后遇到类似的问题就能轻易破解。

答案默认隐藏,意在希望读者在思考之后,再看参考答案。

当然参考答案也不一定完全正确,或许还有更优解,如果你发现了,请提出。

1、查询“C01”课程比“C02”课程成绩高的所有学生的学号

--1) 最笨的方法
--分别得到C01成绩单和C02课程的成绩单,然后再得到C01课程比C02课程高的学生学号
SELECT SID,Score FROM SC WHERE CID='C01' SELECT SID,Score FROM SC WHERE CID='C02' SELECT A.SID FROM
(SELECT SID,Score FROM SC WHERE CID='C01') AS A
INNER JOIN
(SELECT SID,Score FROM SC WHERE CID='C02') AS B
ON A.SID = B.SID WHERE A.Score>B.Score

点击查看,参考答案

2、查询平均成绩大于60分的同学的学号和平均成绩

SELECT SID,AVG(Score) AS ScoreAverage FROM SC GROUP BY SID HAVING AVG(Score)>60 

点击查看,参考答案

3、查询所有同学的学号、姓名、选课数、总成绩

--1)通过Group查询总成绩和选课数,然后再联表查询
SELECT SID,COUNT(CID) AS CourseCount,SUM(Score) as SumScore FROM SC GROUP BY SID SELECT Student.SID,SName,CourseCount,SumScore FROM Student
LEFT JOIN
(SELECT SID,COUNT(CID) AS CourseCount,SUM(Score) as SumScore FROM SC GROUP BY SID) AS B
ON Student.SID = B.SID --2)联表查询后再GROUP By
SELECT Student.SID,Student.Sname,COUNT(SC.CID),SUM(Score)
FROM Student LEFT OUTER JOIN SC ON Student.SID=SC.SID
GROUP BY Student.SID,Sname

参考答案

4、查询姓“李”的老师的个数,不能重复

SELECT COUNT(DISTINCT(TID)) FROM Teacher WHERE TName LIKE '李%'

参考答案

5、查询没学过“张三”老师课的同学的学号、姓名

--1)查询没有学过“张三”老师课的同学的学号,然后再查询得到学生姓名
SELECT SID FROM SC
LEFT JOIN Course ON SC.CID = Course.CID
LEFT JOIN Teacher ON Course.TID = Teacher.TID WHERE Tname ='张三' SELECT SID,Sname FROM Student WHERE SID NOT IN (SELECT SID FROM SC
LEFT JOIN Course ON SC.CID = Course.CID
LEFT JOIN Teacher ON Course.TID = Teacher.TID WHERE Tname ='张三') --2)先查询张三老师的所有课程,然后查询选择了张三老师课程的学生ID,最后查询未选其课程的学生信息
SELECT CID FROM Course INNER JOIN Teacher ON Course.TID = Teacher.TID WHERE Teacher.TName='张三' SELECT SID FROM SC LEFT JOIN
(SELECT CID FROM Course INNER JOIN Teacher ON Course.TID = Teacher.TID WHERE Teacher.TName='张三') AS TeacherCID
ON SC.CID = TeacherCID.CID SELECT SID,SName FROM Student WHERE SID NOT IN
(
SELECT SID FROM SC LEFT JOIN
(SELECT CID FROM Course INNER JOIN Teacher ON Course.TID = Teacher.TID WHERE Teacher.TName='张三') AS TeacherCID
ON SC.CID = TeacherCID.CID
) --3)查询多表,获取张三老师的课程
SELECT Student.SID,Student.SName FROM Student
WHERE SID NOT IN
(SELECT DISTINCT(SC.SID) FROM SC,Course,Teacher WHERE SC.CID=Course.CID and Teacher.TID=Course.TID and Teacher.Tname='张三')

参考答案

6、查询两门以上不及格课程的同学的学号及其平均成绩

--1)查询有课程不及格的学生ID
SELECT DISTINCT(SID) FROM SC WHERE Score<60
SELECT SID,AVG(Score) AS ScoreAverage FROM SC GROUP BY SID HAVING COUNT(SID)>2 AND SID IN (SELECT DISTINCT(SID) FROM SC WHERE Score<60) --2)查询有两门以上不及格的学号
SELECT SID FROM SC WHERE Score<60 GROUP BY SID HAVING COUNT(SID)>2 SELECT SID,AVG(ISNULL(Score,0)) FROM SC
WHERE SID IN (SELECT SID FROM SC WHERE Score<60 GROUP BY SID HAVING COUNT(SID)>2)
GROUP BY SID

参考答案

7、查询全部学生都选修的课程的课程号和课程名

--查询各个课程的学生总数
SELECT CID,COUNT(DISTINCT(SID)) AS SCount FROM SC GROUP BY CID
--查询学生的总数
SELECT COUNT(DISTINCT(SID)) AS SCount FROM Student --得到结果
SELECT CID,CName FROM Course
WHERE CID IN (SELECT CID FROM SC GROUP BY CID
HAVING COUNT(DISTINCT(SID))=(SELECT COUNT(DISTINCT(SID)) AS SCount FROM Student))

参考答案

8、统计每门课程的学生选修人数(超过10人的课程才统计)

要求输出课程号和选修人数,查询结果按人数降序排列,查询结果按人数降序排列,若人数相同,按课程号升序排列

SELECT CID,COUNT(SID) FROM SC GROUP BY CID HAVING COUNT(SID)>10 ORDER BY COUNT(SID) DESC,CID

参考答案

9、查询每门功成绩最好的前三名,要求输出课程ID、前三名学号以及成绩,并且按照课程号升序排列,同课程的成绩倒叙排列

--1)取前三名
--查询一门课的前三名
SELECT TOP 3 CID,SID,Score FROM SC WHERE CID='C01' ORDER BY Score DESC --查询每门课的前三名
SELECT CID,SID,Score FROM SC AS A
WHERE SID IN (SELECT TOP 3 SID FROM SC WHERE CID=A.CID ORDER BY Score DESC)
ORDER BY CID,Score DESC

参考答案1

如果成绩有并列现象

--2)按分数取前三名,可以并列
--如果有并列分数就有问题了,可能前三名不止3人,应该按分数处理
SELECT CID,SID,Score FROM SC AS A
WHERE Score IN (SELECT TOP 3 Score FROM SC WHERE CID=A.CID ORDER BY Score DESC)
ORDER BY CID,Score DESC

参考答案2

加上排名

--3)相比第二种方法更合理,再深入一下,查询结果加上排名
SELECT CID,SID,Score,Place=(SELECT COUNT(Score) FROM SC AS B WHERE B.CID=A.CID AND B.Score>A.Score)+1 FROM SC AS A
WHERE Score IN (SELECT TOP 3 Score FROM SC WHERE CID=A.CID ORDER BY Score DESC)
ORDER BY CID,Score DESC

参考答案3

10、查询选修“张三老师所授课程的学生中,成绩最高的学生姓名及其成绩

--(1)根据教师姓名查询其所授课程ID
SELECT CID FROM Course WHERE Course.TID IN (SELECT TID FROM Teacher WHERE Teacher.TName='张三')
--(2)查询一门课的最高成绩
SELECT TOP 1 Score FROM SC WHERE CID='C01' ORDER BY Score DESC
--(3)查询所有课程中成绩最高的学生ID,成绩
SELECT SID,CID,Score FROM SC AS A WHERE A.Score IN (SELECT TOP 1 Score FROM SC AS B WHERE A.CID=B.CID ORDER BY B.Score DESC)
--(4)查询张三教师所授课程的成绩最高的学生ID\成绩,
SELECT SID,CID,Score FROM SC AS A WHERE A.CID IN(SELECT CID FROM Course WHERE Course.TID IN (SELECT TID FROM Teacher WHERE Teacher.TName='张三')) AND A.Score IN (SELECT TOP 1 Score FROM SC AS B WHERE A.CID=B.CID ORDER BY B.Score DESC)
--(5)查询学生姓名和成绩
SELECT A.SID,Student.SName,Score FROM SC AS A
LEFT JOIN Student ON A.SID = Student.SID
WHERE A.CID IN(SELECT CID FROM Course WHERE Course.TID IN (SELECT TID FROM Teacher WHERE Teacher.TName='张三'))
AND A.Score IN (SELECT TOP 1 Score FROM SC AS B WHERE A.CID=B.CID ORDER BY B.Score DESC)
--(6)查询优化

参考答案

11、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程号升序排列

SELECT CID,AVG(Score) FROM SC GROUP BY CID ORDER BY AVG(Score) DESC,CID

参考答案

12、查询学生总成绩以及名次

--(1)查询学生总成绩
SELECT SID,SUM(Score) FROM SC GROUP BY SID --(2)查询总排名
SELECT SID,TotalScore,
Place=(SELECT COUNT(DISTINCT(TotalScore)) FROM (SELECT SID,SUM(Score) AS TotalScore FROM SC GROUP BY SID) AS T1 WHERE T1.TotalScore> T2.TotalScore) +1
FROM (SELECT SID,SUM(Score) AS TotalScore FROM SC GROUP BY SID) AS T2
ORDER BY Place,SID

参考答案1

如果有的学生未选课怎么办

--2)需要查询所有学生的排名,有的学生没有选课,成绩为0

SELECT SID,TotalScore,
Place=(SELECT COUNT(DISTINCT(TotalScore)) FROM (SELECT SID,SUM(Score) AS TotalScore FROM SC GROUP BY SID) AS T1 WHERE T1.TotalScore> T3.TotalScore) +1
FROM (SELECT Student.SID,Student.SName,ISNULL(TotalScore,0) AS TotalScore FROM Student LEFT JOIN (SELECT SID,SUM(Score) AS TotalScore FROM SC GROUP BY SID) AS T2 ON Student.SID = T2.SID) AS T3
ORDER BY Place,SID

参考答案

13、统计各科成绩,各分数段人数,结果包括:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60]

SELECT SC.CID AS 课程ID,CName AS 课程名称
,SUM(CASE WHEN Score BETWEEN 85 AND 100 THEN 1 ELSE 0 END) AS [100 - 85]
,SUM(CASE WHEN Score BETWEEN 70 AND 85 THEN 1 ELSE 0 END) AS [85 - 70]
,SUM(CASE WHEN Score BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS [70 - 60]
,SUM(CASE WHEN Score < 60 THEN 1 ELSE 0 END) AS [60 -]
FROM SC,Course
where SC.CID=Course.CID
GROUP BY SC.CID,Cname

参考答案

14、查询各科的及格率

SELECT CID,
SUM(CASE WHEN Score>=60 THEN 1 ELSE 0 END) AS Pass,
SUM(CASE WHEN Score<60 THEN 1 ELSE 0 END) AS Fail
FROM SC GROUP BY CID --2)再查询及格率
SELECT CID,Pass/(Pass + Fail) FROM
(
SELECT CID,
SUM(CASE WHEN Score>=60 THEN 1 ELSE 0 END) AS Pass,
SUM(CASE WHEN Score<60 THEN 1 ELSE 0 END) AS Fail
FROM SC GROUP BY CID
) AS T1

参考答案

15、求各科成绩的最高分和最低分

SELECT CID,MAX(Score),MIN(Score) FROM SC GROUP BY CID

参考答案

16、查询出生1990年之前的学生名单

SELECT  DATEPART(YEAR,SAge),* FROM Student WHERE DATEPART(YEAR,GETDATE())-SAge < 1990

参考答案

17、查询选课少于两门课程的学生名单

--1)以下结果错误,还有没选课的学生
SELECT SID,SName FROM Student WHERE SID IN (
SELECT SID FROM SC GROUP BY SID HAVING COUNT(CID)<2) --2)用其否定,NOT IN
SELECT SID,SName FROM Student WHERE SID NOT IN (
SELECT SID FROM SC GROUP BY SID HAVING COUNT(CID)>=2)

参考答案

18、查询英语成绩第三名的学生成绩单

--1)查询英语课程ID
SELECT CID FROM Course WHERE CName='英语'
--2)查询英语所有成绩
SELECT DISTINCT Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英语')
--3)查询前三名成绩
SELECT DISTINCT TOP 3 Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英语') ORDER BY Score ASC
--4)查询第三名成绩
SELECT TOP 1 Score FROM (SELECT DISTINCT TOP 3 Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英语') ORDER BY Score ASC) AS TopThree --5)查询学生ID
SELECT SID FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英语') AND Score= (SELECT TOP 1 Score FROM (SELECT DISTINCT TOP 3 Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英语') ORDER BY Score ASC) AS TopThree) --6)查询学生成绩单
SELECT SID,CID,Score FROM SC WHERE SID IN (
SELECT SID FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英语') AND Score= (SELECT TOP 1 Score FROM (SELECT DISTINCT TOP 3 Score FROM SC WHERE CID = (SELECT CID FROM Course WHERE CName='英语') ORDER BY Score ASC) AS TopThree)
)

查看答案

SQL总结(七)查询实战的更多相关文章

  1. SQL Server 性能优化实战系列(二)

    SQL Server datetime数据类型设计.优化误区 一.场景 在SQL Server 2005中,有一个表TestDatetime,其中Dates这个字段的数据类型是datetime,如果你 ...

  2. C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法

    C#构造方法(函数)   一.概括 1.通常创建一个对象的方法如图: 通过  Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...

  3. SQL Fundamentals: 子查询 || 分析函数(PARTITION BY,ORDER BY, WINDOWING)

    SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...

  4. CASE函数 sql server——分组查询(方法和思想) ref和out 一般处理程序结合反射技术统一执行客户端请求 遍历查询结果集,update数据 HBuilder设置APP状态栏

    CASE函数   作用: 可以将查询结果集的某一列的字段值进行替换 它可以生成一个新列 相当于switch...case和 if..else 使用语法: case 表达式/字段 when 值 then ...

  5. Spark SQL知识点大全与实战

    Spark SQL概述 1.什么是Spark SQL Spark SQL是Spark用于结构化数据(structured data)处理的Spark模块. 与基本的Spark RDD API不同,Sp ...

  6. Sql Server中查询今天、昨天、本周、上周、本月、上月数据

    Sql Server中查询今天.昨天.本周.上周.本月.上月数据 在做Sql Server开发的时候有时需要获取表中今天.昨天.本周.上周.本月.上月等数据,这时候就需要使用DATEDIFF()函数及 ...

  7. sql跨库查询

    ---------------------------------------------------------------------------------- --1. 创建链接服务器 --1. ...

  8. SQL 数据分页查询

    最近学习了一下SQL的分页查询,总结了以下几种方法. 首先建立了一个表,随意插入的一些测试数据,表结构和数据如下图: 现在假设我们要做的是每页5条数据,而现在我们要取第三页的数据.(数据太少,就每页5 ...

  9. SQL表连接查询(inner join、full join、left join、right join)

    SQL表连接查询(inner join.full join.left join.right join) 前提条件:假设有两个表,一个是学生表,一个是学生成绩表. 表的数据有: 一.内连接-inner ...

随机推荐

  1. 初识python中的类与对象

    这篇博客的路线是由深入浅,所以尽管图画的花花绿绿的很好看,但是请先关注我的文字,因为初接触类的小伙伴直接看类的实现可能会觉得难度大,只要耐着性子看下去,就会有一种“拨开迷雾看未来”的感觉了. 一.py ...

  2. hdu 5875 ACM/ICPC Dalian Online 1008 Function

    题目链接 分析:用RMQ预处理每段的最小值,然后对每次查询的区间找最靠近左边的小于的值,取模后递归操作.因为每次取模至少会使原来的值减半,所以递归操作是的.每次查询最小值如果通过线段树那么最终的复杂度 ...

  3. to my friends-Don't give up so fast

    早上听到大学挺要好的朋友突然说要换行,心情就一股莫名的哀伤,因为当初是三个人一起约定好的,要朝着我们共同的目标而努力奋斗的,这股热情怎能这么轻易地被现实的冷水浇灭.没错,我们是刚出社会的毛头小子,我们 ...

  4. zookeeper学习系列:三、利用zookeeper做选举和锁

    之前只理解zk可以做命名,配置服务,现在学习下他怎么用作选举和锁,进一步还可构建master-slave模式的分布式系统. 为什么叫Zoo?“因为要协调的分布式系统是一个动物园”. ZooKeeper ...

  5. post multipart data boundary问题 使用curl 向jersey post文件

    原以为curl 模拟post file跟post string类似,-d参数一加 ,header一加就完了,这次遇到个问题,却怎么都搞不定. curl模拟post提交 与客户端定的协议是: Heade ...

  6. R语言apply函数族笔记

    为什么用apply 因为我是一个程序员,所以在最初学习R的时候,当成“又一门编程语言”来学习,但是怎么学都觉得别扭.现在我的看法倾向于,R不是一种通用型的编程语言,而是一种统计领域的软件工具.因此,不 ...

  7. IOS中的动画菜单

    SvpplyTable(可折叠可张开的菜单动画) 允许你简单地创建可折叠可张开的菜单动画效果,灵感来自于Svpply app.不同表格项目使用JSON定义,你可以定义每个菜单项和任何子菜单,为每个项目 ...

  8. CodeForces 688D-Remainders Game

    题意: 已知n, k与n个整数(c1,c2,...,cn),问你是否存在一个数x,使得它能被n个整数且k整除. 分析: 可以先将n个整数的最小公倍数lcm计算出来,再判断它是否能被k整除. 代码如下: ...

  9. python分割字符串split,filter函数用法

    现有字符串,需要取出用空格分隔的第一段,操作如下 >>> product_model = ‘WS-C2960G-24TC-L – Fixed Module 0′>>> ...

  10. MySQL字符集乱码

    学数据库,最让人丧气的就是字符集的问题了,一旦出问题,就会有砸电脑的冲动,特别是在修改很多次字符集后依然不成功的时候! 我用的数据库软件是MySQL 5.1.28.最初出问题的时候,是这样的: 情景一 ...