数据查询
数据查询一般格式为:
SELECT [ALL|DISTINCT]<目标列表达式>[,<目标列表达式>]···
FROM<表名或视图名>[,<表名或视图名>···]|(<SELECT语句>)[AS]<别名>
[WHERE<条件表达式>]
[GROUP BY<列名1>[HAVING<条件表达式>]]
[ORDER BY<列名2>[ASC |DESC]];
整个SELECT语句的含义是,根据WHERE子句的条件表达式从FROM子句指定的基本表、视图或派生表中找出满足条件的元组,再按SELECT子句中的目标列表达式选出元组中的属性值形成结果表。
如果有GROUP BY 子句,则将结果按<列名1>的值进行分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。如果GROUP BY子句带HAVING短语,则只有满足指定条件的组才予以输出。
如果有ORDER BY子句,则结果表还要按照<列名2>的值的升序或降序排序。
单表查询
查询全体学生的姓名、学号、所在系
Use school1
GO
SELECT Sname,Sno,Sdept
FROM Student
查询每个学生的详细记录
Use school1
GO
SELECT *
FROM Student
查询全体学生的姓名及其出生年份
Use school1
GO
SELECT Sname,2014-Sage /* 查询结果的第二列是一个算数表达式*/
FROM Student
查询全体学生的姓名、出生年份和所在的院系,要求用小写字母表示系名
Use school1
GO
SELECT Sname,'Year of Birth',2014-Sage,LOWER(Sdept)
FROM Student
可以通过指定别名来改变查询结果的列标题
Use school1
GO
SELECT Sname,'Year of Birth',2014-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENT
FROM Student
消除重复的行
查询选修了课程的学生学号
Use school1
GO
SELECT Sno
FROM SC
查询结果中包含了许多重复的行。我们可以指定DISTINCT来去掉表中的重复行。
Use school1
GO
SELECT DISTINCT Sno
FROM SC
WHERE子句常用查询条件
查询条件 | 谓词 |
比较 | =,>,<,>=,<=,!=,<>,!>,!<;NOT+上述比较运算符 |
确定范围 | BETWEEN AND,NOT BETWEEN AND |
确定集合 | IN,NOT IN |
字符匹配 | LIKE,NOT LIKE |
空值 | IS NOLL,IS NOT NULL |
多重条件(逻辑运算) | AND,OR,NOT |
查询所有年龄在20岁以下的学生姓名及其年龄
Use school1
GO
SELECT Sname,Sage
FROM Student
WHERE Sage<20;
查询年龄不在20~23岁之间的学生姓名、系别和年龄
Use school1
GO
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage NOT BETWEEN 20 AND 23;
谓词IN可以用来查找属性值属于指定集合的元组。
查找计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别。
Use school1
GO
SELECT Sname,Ssex
FROM Student
WHERE Sdept IN ('计算机','数学','信息');
字符匹配
谓词LIKE可以用来进行字符串的匹配。
查询所有姓刘的同学的姓名、学号和 性别。
Use school1
GO
SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname LIKE '刘%'
查询姓“范”且全名为三个汉字的学生的姓名
Use school1
GO
SELECT Sname
FROM Student
WHERE Sname LIKE '范__';
查询名字中第二个字为“林”的学生的姓名和学号
Use school1
GO
SELECT Sname
FROM Student
WHERE Sname LIKE '_林%';
查询缺少成绩的学生的学号和相应的课程号
某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号。
Use school1
GO
SELECT Sno,Cno
FROM SC
WHERE Grade IS NULL;
注意,这里的IS不能用等号代替。
ORDER BY 子句
用户可以用ORDER BY子句对查询结果按照一个或多个属性列的升序(ASC)或降序(DESC)排列,默认值为升序。
查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列
Use school1
GO
SELECT *
FROM Student
ORDER BY Sdept,Sage DESC;
聚集函数
COUNT(*) | 统计元组个数 |
COUNT([DISTINCT ALL])<列名> | 统计一列中值的个数 |
SUM | 计算一列值的总和(此列必须是数值型) |
AVG | 计算一列值的平均值(此列必须是数值型) |
MAX | 求一列值中的最大值 |
MIN | 求一列值中的最小值 |
查询学生总人数
Use school1
GO
SELECT COUNT(*)
FROM Student
查询选修了课程的学生人数
Use school1
GO
SELECT COUNT(DISTINCT Sno)
FROM SC
计算选修1号课程的学生平均成绩
Use school1
GO
SELECT AVG(Grade)
FROM SC
WHERE Cno='C01'
查询选修1号课程的学生的最高分数
Use school1
GO
SELECT MAX(Grade)
FROM SC
WHERE Cno='C01'
查询学生S01选秀课程的总学分数
Use school1
GO
SELECT SUM(Credit)
FROM SC,Course
WHERE Sno='S01' AND SC.Cno=Course.Cno
验证:
GROUP BY 子句
GROUP BY子句将查询结果按某一列或多列的值分组,值相等的为一组。
分组后聚集函数将作用于每一个组,即每一个组都有一个函数值。
求各个课程号及相应的选课人数
Use school1
GO
SELECT Cno,COUNT(Sno)
FROM SC
GROUP BY Cno
查询选修了三门及以上课程的学生学号
Use school1
GO
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(*)>=3
查询平均成绩大于等于80分的学生学号和平均成绩
Use school1
GO
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade)>=80
连接查询
等值与非等值连接查询
查询每个学生及其选修课程的情况
Use school1
GO
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno=SC.Sno
查询选修2号课程且成绩在90分以上的所有学生的学号和姓名
Use school1
GO
SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND SC.Cno='C02' AND SC.Grade>90
自身连接
连接操作不仅可以在两个表中进行,也可以是一个表与其自己进行连接,称为表的自身连接。
查询每一门课的间接先修课
Use school1
GO
SELECT FIRST.Cno,SECOND.Pre_Cno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cno=SECOND.Pre_Cno
外连接
查询填入空值
在“查询每个学生及其选修课程的情况”中,没有选课的学生没有数据,如果想要这些学生的数据,而选课填上空值NULL,则可以使用外连接:
Use school1
GO
SELECT Student.Sno,Sname,Cno,Grade
FROM Student LEFT OUTER JOIN SC ON (Student.Sno=SC.Sno)
多表连接
查询每个学生的学号、姓名、选修的课程名及成绩
Use school1
GO
SELECT Student.Sno,Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno
嵌套查询
在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块。
将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。
带有IN谓词的子查询
查询与“李伟”在同一个系学习的学生
Use school1
GO
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname='李伟'
)
查询选修了课程名为“数据库”的学生学号和姓名
Use school1
GO
SELECT Sno,Sname
FROM Student
WHERE Sno IN
(SELECT Sno
FROM SC
WHERE Cno IN
(SELECT Cno
FROM Course
WHERE Cname=' 数据库'
)
);
带有比较运算符的子查询
找出每个学生超过他自己选修课程平均成绩的课程号
Use school1
GO
SELECT Sno,Cno
FROM SC x
WHERE Grade >= (SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno
)
查询非计算机科学系中比计算机科学系任意一个学生年龄大的学生姓名和年龄
Use school1
GO
SELECT Sname,Sage
FROM Student
WHERE Sage>ANY(SELECT Sage
FROM Student
WHERE Sdept='计算机')
AND Sdept<>'CS'
带有EXITS谓词的子查询
带有EXITS谓词的子查询不返回任何数据,只产生逻辑真值true或逻辑假值false
查询所有选修了1号课程的学生姓名
Use school1
GO
SELECT Sname
FROM Student
WHERE EXISTS(
SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno='C01'
)
使用存在量词EXISTS后,若内层查询结果非空,则外层的WHERE子句返回真值,否则返回假值。
查询没有选修1号课程的学生姓名
Use school1
GO
SELECT Sname
FROM Student
WHERE NOT EXISTS(
SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno='C01'
)
查询选修了全部课程的学生姓名
SQL中没有全称量词,可以将题目的意思转换成等价的用存在量词的形式:
查询这样的学生,没有一门课程是他不选修的
Use school1
GO
SELECT Sname
FROM Student
WHERE NOT EXISTS(
SELECT *
FROM Course
WHERE NOT EXISTS(
SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno=Course.Cno
)
)
答案是并没有这样的卷王
集合查询
SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作。
集合操作主要包括并操作UNION、交操作INTERSECT和差操作EXCEPT
注意,参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同
查询数学系的学生及年龄不大于19岁的学生
Use school1
GO
SELECT *
FROM Student
WHERE Sdept='数学'
UNION
SELECT *
FROM Student
WHERE Sage<=19
查询选修了课程1或者选修了课程2的学生
本例即查询选修课程1与选修课程2的学生集合的并集
Use school1
GO
SELECT Sno
FROM SC
WHERE Cno='C01'
UNION
SELECT Sno
FROM SC
WHERE Cno='C02'
查询数学系的学生与年龄不大于19岁的学生的交集
Use school1
GO
SELECT *
FROM Student
WHERE Sdept='数学'
INTERSECT
SELECT *
FROM Student
WHERE Sage<=19
查询既选修课课程1又选修了课程2的学生
就是查询选修课程1的学生集合与选修课程2的学生集合的交集
Use school1
GO
SELECT Sno
FROM SC
WHERE Cno='C01'
INTERSECT
SELECT Sno
FROM SC
WHERE Cno='C02'
查询数学系的学生与年龄不大于19岁的学生的差集
Use school1
GO
SELECT *
FROM Student
WHERE Sdept='数学'
EXCEPT
SELECT *
FROM Student
WHERE Sage<=19