SQL之数据查询
文章为个人读书总结笔记 发现错误以及如果有什么建议可以及时通知我哟!
SQL语言使用SELECT
语句进行查询数据
格式
SELECT [ALL|DISTINCT] <目标表达式> [,<目标表达式>] ... FROM <表名或者视图名> [,<表名或者视图名>...] | (<SELECT语句>)[AS]<别名> [WHERE <条件表达式> ] [GROUP BY <列名1> [HAVING <条件表达式>]] [ORDER BY <列名2> [ASC|DESC]];
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 含义
- 根据
WHERE
子句的条件表达式 从FROM
子句指定的基本表或者视图找出满足条件元组 - 再按
SELECT
子句罗列出的表达式选出元组中的属性值形成结果表 - 如果有
GROUP BY
子句,将结果表按<列名1>
值进行划分组,值相同为一组 - 如果
GROUP BY
子句带有HAVING
条件短语,则以组为单位,选出满足条件的组 - 如果有
ORDERBY
子句,将结果表按照<列名2>
的值进行升序或者降序处理
ASC
: 升序DESC
: 降序
- 根据
假如我想:单表查询
实现:选择表中的若干列(SELECT
我能:查询指定列
例子:查询表S的所有Sno, Sname
SELECT Sno,Sname FROM S;
- 1
- 2
- 执行过程
- 从S表中取出一个元组
- 选择元组的Sno, Sname的属性值形成一个新的元组作为输出
- 对S表中的其他元组做同样的处理
- 形成最终结果关系输出
例子:查询S表中的所有Sname,Sno,Sdept
SELECT Sname,Sno,Sdept FROM S;
- 1
- 2
- 注意:目标表达式中各个列的顺序可以与查询表中的顺序不同( 由用户自定义结果表
我能:查询全部列
例子:查询全部S表的所有属性
- 方法一 : 列出完整目标表达式
SELECT Sno,Sname,Sdept,Sage FROM S;
- 1
- 2
- 方法二 : 使用 * 代替整个目标表达式
SELECT * FROM S;
- 1
- 2
我能:查询经过计算后得到的值
补充:目标表达式
不仅可以是表中的属性列
例子参照上面罗列出来的
还可以是表达式 ( 例如针对整数的减法运算
例子:查询S表的Sname,以及出生年份( 2018 - Sage
SELECT Sname,2018-Sage FROM S;
- 1
- 2
还可以是字符串常量
例子:查询S表的Sname,添加字符串 “Year of Birth:’ 属性列,以及出生年份
SELECT Sname,'Year of Birth:',2018-Sage FROM S;
- 1
- 2
还可以是函数
例子:查询S表中的Sdept,要求数据为小写
SELECT LOWER(Sdept) FROM S;
- 1
- 2
补充:为目标表达式指定别名
例子:查询表S,结果表为表达式 2018-Sage 指定别名为BIRTHDAY
影响:结果表中的属性列标题由
2018-Sage
变成了BIRTHDAY
SELECT 2018-Sage BIRTHDAY, Sname FROM S;
- 1
- 2
实现:选择表中的若干元组(WHERE
我能:消除取值重复的行(DISTANCT
使用:
DISTINCT
例子:查询SC表中的Sno,消除重复的行
SELECT DISTANCT Sno FROM SC;
- 1
- 2
我能:查询满足条件的元组(WHERE
- 常用的查询条件 ( 条件表达式
查询条件 | 谓词 |
---|---|
比较 | [NOT] =,>,<,>=,<=,!=,<>,!>,!< |
确定范围 | [NOT] BETWEEN AND |
确定集合 | [NOT] IN |
字符匹配 | [NOT] LIKE |
空值 | IS [NOT] NULL |
多重条件(逻辑运算) | AND, OR, NOT |
比较大小
=
:等于>
: 大于<
:小于>=
:大于等于<=
:小于等于!=
或<>
:不等于!>
:不大于!<
:不小于例子:查询S表中,满足Sdept=’CS’的所有元组,选择Sname输出
SELECT Sname FROM S WHERE Sdept='CS';
- 1
- 2
- 3
确定范围
BETWEEN 下限 AND 上限
NOT BETWEEN 下限 AND 上限
例子:从S表中查询Sage在20~23之间的数据,输出Sname,Sage
SELECT Sname,Sage FROM S WHERE Sage BETWEEN 20 AND 23;
- 1
- 2
- 3
确定集合
IN
: 给出域(集合),确定是否在域内NOT IN
例子:从S表中查询满足Sdept值在给定值域(‘CS’,’MA’,’IS’)内,输出Sname,Ssex
SELECT Sname,Ssex FROM S WHERE Sdept IN ('CS','MA','IS');
- 1
- 2
- 3
字符匹配
LIKE
NOT LIKE
格式:
[NOT] LIKE '<匹配串>' [ESCAPE '<换码字符>']
- 1
含义
- 查找的元组的指定属性列值要满足与
<匹配串>
相匹配
- 查找的元组的指定属性列值要满足与
匹配串
- 完整字符串
- 含有通配符
%
和_
的字符串 %
: 代表任意长度字符串( 甚至是0 ( 即空串
- 例如:
a%b
代表以a开头,以b结尾的所有字符串 - acdb, acb, ab, …
- 例如:
_
:代表任意当个字符
- 例如:
a_b
代表以a开头,以b结尾的长度为3的所有字符串 - acb, adb, …
- 例如:
ESCAPE '<换码字符>'
当匹配串本身就想含有通配符
%
或者_
, 则需要转义例如:从C表中查询Cname为’DB_Design’的元组,输出Cno
SELECT Cno FROM C WHERE Cname LIKE 'DE\_Design' ESCAPE'\';
- 1
- 2
- 3
例子:从S表中查询Sno为’201215121’的元组,并输出全部信息
SELECT * FROM S WHERE Sno LIKE '201215121'; 补充:不含通配符 LIKE 等价于 = SELECT * FROM S WHERE Sno = '201215121';
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
涉及空值的查询
IS NULL
不能有
=
代替IS
IS NOT NULL
例子:查询SC表中Grade为空值的元组,输出Sno,Cno
SELECT Sno,Cno FROM SC WHERE Grade IS NULL;
- 1
- 2
- 3
多重条件查询
AND
: 优先级高于OR
(注意短路OR
:IN
实际上是多个OR
的缩写例子:从S表中查询Sdept为CS,并且Sage< 20的元组,输出Sname
SELECT Sname FROM S WHERE Sdept='CS' AND Sage<20;
- 1
- 2
- 3
实现:ORDER BY
子句
例子:从SC表中查询Cno为3的元组,结果表包含Sno,Grade,然后按照Grade降序输出
SELECT Sno,Grade FROM SC WHERE Cno=3 ORDER BY Grade DESC;
- 1
- 2
- 3
- 4
- 注意:空值
- 对于空值,排序时显示的次序由具体的系统来决定
使用:聚集函数
函数及格式 | 含义 |
---|---|
COUNT(*) | 统计元组个数 |
COUNT( [DISTANCT|ALL ] <列名>) | 统计一列中值的个数 |
SUM( [DISTANCT|ALL ] <列名> ) | 计算某一列值总和( 数值类型列) |
AVG( [DISTANCT|ALL ] <列名>) | 计算某一列值平均值( 数值类型列) |
MAX( [DISTANCT|ALL ] <列名>) | 求某一列的最大值 |
MIN( [DISTANCT|ALL ] <列名>) | 求某一列的最小值 |
(注意:DISTANCT
: 不重复(默认是ALL
:可取重复值
例子:查询S表的元组数目并输出
SELECT COUNT(*) FROM S;
- 1
- 2
注意:空值
除了
COUNT(*)
外的聚集函数跳过空值,处理非空值注意使用环境
用于
SELECT
子句和GROUP BY
(下目将会介绍)中的HAVING
子句- 不能用于
WHERE
子句
实现:GROUP BY
子句
分组的目的
- 细化聚集函数的作用对象(分组后,聚集函数作用于组,有组则作用于组
例子:从SC表中按Cno进行分组,然后输出Cno,以及COUNT(Sno)
SELECT Cno,COUNT(Sno) FROM SC GROUP BY Cno;
- 1
- 2
- 3
- 执行步骤
- 从SC表选择元组
- 按照Cno对元组进行分组
- 输出分组后的Cno,输出分组后每组的COUNT(Sno)
补充:对组的限制条件
HAVING
子句HAVING
与WHERE
的区别:作用对象不同HAVING
作用于分组WHERE
作用于基本表或视图
例子:从SC表中选择元组,按Sno分组,选出组中的元组数目大于3的组别,输出Sno
SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*)>3;
- 1
- 2
- 3
- 4
假如我想:连接查询( FROM
- 定义:查询同时涉及两个以上的表
- 地位:关系数据库中最主要的查询
- 分类
- 等值连接查询
- 自然连接查询
- 非等值连接查询
- 自身连接查询
- 外连接查询
- 复合条件连接查询
实现:等值与非等值连接
连接两个表
连接条件(连接谓词
- 定义:
WHERE
子句连接两个表的条件部分
- 定义:
关键子句:
WHERE
格式
[<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>
- 1
比较运算符:=,>, < , …
=
:等值连接- 去掉重复的等值连接:自然连接
其他为非等值连接
特殊:连接谓词
BETWEEN ... AND ...
[<表名1>.]<列名1> BETWEEN [<表名2>.]<列名2> AND [<表名2>.]<列名3>
- 1
- 连接字段
- 定义:连接谓词中的列名
- 限制:需要具备可比性
例子
- 按照Sno属性值连接S表和SC表,并全部输出
SELECT S.*, SC.* FROM S,SC WHERE S.sno = SC.sno;
- 1
- 2
- 3
- 按照Sno属性自然连接S表和SC表,并输出
SELECT S.sno,Sname,Ssex,Sdept,Cno,Grade FROM S,SC WHERE S.Sno = SC.Sno;
- 1
- 2
- 3
- 运用连接谓词和选择谓词的复合条件
SELECT S.Sno,Sname FROM S,SC WHERE S.Sno = SC.Sno AND SC.Cno = '2' AND SC.Grade > 90;
- 1
- 2
- 3
- 4
- 5
- 6
- 执行步骤
- 从SC表中选择符合条件的元组按照Sno等值连接S表
- 再输出S.Sno和Sname
- 特点:较普通连接高效
实现:自身连接
定义:一个表与自己进行连接
限制:需要指定别名
例子:对C表进行按照Cpno和Cno进行自身等值连接,输出Cno和Cpno
SELECT FIRST.Cno, SECOND.Cpno FROM C FIRST,C SECOND WHERE FIRST.Cpno = SECOND.Cno;
- 1
- 2
- 3
组略演示 FIRST.Cno FIRST.Cpno SECOND.Cno SECOND.Cpno => FIRST.Cno SECOND.Cpno
- 1
- 2
- 3
- 4
- 5
实现:外连接
定义:保留正常连接中不符合条件的元组,未连接的部分用空值占位
左外连接:保留坐边,填充未连接的右边(列出全部左边中的元组
右外连接:保留右边,填充未连接的左边(列出全部右边中的元组
格式
左外 <表名2> LEFT OUTER JOIN <表名2> ON (<条件表达式>) 右外 <表名2> LEFT OUTER JOIN <表名2> ON (<条件表达式>)
- 1
- 2
- 3
- 4
例子:S表左外连接SC表
SELECT S.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM S LEFT OUTER JOIN SC ON(S.Sno = SC.Sno);
- 1
- 2
实现:多表连接
定义:两个以上的表进行连接
例子:按Sno连接S表和SC表,再将结果按Cno连接C表,选择属性输出
SELECT S.Sno,Sname,Cname,Grade FROM S,SC,C WHERE S.Sno = SC.Sno AND SC.Cno = C.Cno;
- 1
- 2
- 3
假如我想:嵌套查询
定义:将查询块嵌套在另外一个查询块的
WHERE
或者HAVING
短语条件中的查询- 查询块
- 定义:
SELECT-FROM-WHERE
语句
例如
SELECT Sname FROM S WHERE S IN( SELECT Sno FROM SC WHERE Cno = '2'); )
- 1
- 2
- 3
- 4
- 5
- 6
- 7
SQL结构化的含义:嵌套查询方式
实现:带有IN
谓词的子查询
详细的例子:查询与 ”刘某“在同一个系学习的学生(采用分步查询再构造嵌套查询
- 一、确定”刘某“所在系
SELECT Sdept FROM S WHERE Sname='刘某'; 假设结果为 'CS'
- 1
- 2
- 3
- 4
- 二、查找所有在’CS’系学习的学生
SELECT Sno,Sname,Sdept FROM S WHERE Sdept='CS';
- 1
- 2
- 3
- 三、构造嵌套查询
SELECT Sno,Sname,Sdept FROM S WHERE Sdept IN( SELECT Sdept FROM S WHERE Sname='刘某' );
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 本例为不相关子查询
- 子查询不依赖于父查询( 依赖则称:相关子查询( 下目有相关例子
实现:带有比较运算符的子查询
例子:从SC表中找出超过自己Grade值的Cno,输出Sno和Cno
SELECT Sno,Cno FROM SC x WHERE Grade >=( SELECT AVG(Grade) FROM SC y WHERE y.Sno = x.Sno; )
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 相关子查询需要反复求值(较少遇到
- 父查询每传递一个值到子查询,子查询针对父查询的一个数据完成全部查询
- 重复(父查询继续传递值到子查询
实现:带有ANY(SOME)
或ALL
谓词的子查询
子查询返回值
- 单值:可以用比较运算符, 例如
<=
- 多值:用到谓词修饰(
ALL
和ANY
(有的系统用SOME代替ANY
- 单值:可以用比较运算符, 例如
语义
> ANY
: 大于查询结果中的某个值> ALL
:大于所有值< ANY
:小于某个值< ALL
:小于所有值>= ANY
:大于等于某个值>= ALL
:大于等于所有值<= ANY
:小于等于某个值<= ALL
:小于等于所有值=ALL
:等于所有值=ANY
:等于某一个( IN!= ANY
:不等于某个值!= ALL
:不等于所有值( NOT IN
例子:查询非‘CS’系中比‘CS’系中任意一个学生年龄小的学生的姓名和年龄
SELECT Sname,Sage FROM S WHERE Sage < ANY( SELECT Sage FROM S WHERE Sdept='CS') AND Sdept !='CS'; 聚集函数代替版本 SELECT Sname,Sage FROM S WHERE Sage < ( SELECT MAX(Sage) FROM S WHERE Sdept='CS') AND Sdept !='CS';
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 考虑聚合函数代替谓词修饰
实现:带有EXISTS
谓词的子查询
定义:
EXISTS
为代表存在量词注意:带有
EXISTS
谓词的子查询不返回任何数据,只产生布尔结果(true or false例子:查询所有拥有Cno为1的学生的姓名
SELECT Sname FROM S WHERE EXISTS( SELECT * FROM SC WHERE Sno=S.Sno AND Cno='1');
- 1
- 2
- 3
- 4
- 5
- 6
注意:不存在全称量词和蕴含逻辑运算
- 都需要通过存在量词在构造
假如我想:集合查询
SELECT
语句查询的结果是元组的集合,多个SELECT
语句的结果可以进行集合操作(元组集合运算
集合操作
UNION
:并INTERSECT
:交EXCEPT
:差
限制:操作对象(元组
- 必须满足列数量、列类型相同
例子:查询’CS‘系学生及年龄不大于19的学生
SELECT * FROM S WHERE Sdept='CS' UNION SELECT * FROM S WHERE Sage<=19;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
假如我想:基于派生表的查询
子查询不仅可以出现在WHERE
子句中,还可以出现在FROM
子句中,此时,子查询生成的派生表称主查询的查询对象
例子:前面介绍过的例子,每个学生超过自己选修课程平均成绩的课程号,输出学号和课程号
SELECT Sno,Cno FROM SC,( SELECT Sno,Avg(Grade) FROM SC GROUP BY Sno) AS Avg_sc(avg_sno,avg_grade) WHERE SC.Sno = Avg_sc.avg_sno and SC.Grade >= Avg_sc.avg_grade
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Avg_sc
:FROM子句生成的派生表
- 该表的属性:
avg_sno, avg_grade
- 该表的属性:
- 一些细节
- 问:什么情况下可以不指定属性列,由
SELECT
子句后列名决定? - 答:当
SELECT
后列名没有用到聚集函数时 - 问:什么情况下可以省略
AS
? - 答:基本表均可以省略
AS
,而模式不可以
- 问:什么情况下可以不指定属性列,由
走到最后:SELECT
语句的一般格式
答案在开头, 发现没有,哈哈哈
此文章为转载