SQL 数据查询

数据查询是数据库的核心操作。 SQL 提供了 select 语句进行数据查询。

一、单表查询

1.选择表中的若干列

相当于关系运算中的投影

(1) 查询指定列

1
2
select
from 表名;

(2) 查询全部列

1
2
select *
from 表名;

(3) 查询经过计算的列

1
2
select 包含属性的表达式
from 表名;

(4) 为查询后的列更名

1
2
select 原名 别名, 原名 别名
from 表名;

2.选择表中的若干元组

(1) 清除取值重复的行

关系要求其中的每一个都是唯一的,但两个本来不同的元组在投影后,可能会产生相同的结果。此时可以使用 distinct 清除重复部分

1
2
select distinct
from 表名;

(2) 查询满足条件的元组

1
2
3
select
from 表名
where 条件;

可以和 distinct 配合使用,符合条件的元组只会出现一次

(3) 常用查询条件

比较:

例如:

1
2
3
select name, wages
from payroll
where wages > 10000;

确定范围:

1
where 属性 (not) between 数组下限 and 数值上限

例如:

1
2
3
select name, wages
from payroll
where wages between 1000 and 10000;

确定集合:

1
where 属性 (not) in (属性集合)

例如:

1
2
3
select num, color
from ball
where color in ('red', 'black');

字符匹配:

like 可以用于进行字符串的匹配,其一般格式为:

1
where 属性 (not) like '匹配串'
  • 寻找指定属性列中与匹配串相匹配的元组。

  • 匹配串可以是一个字符串,也可以包含通配符。

  • 通配符:

    • %:代表任意长度(可以为零)的字符串
    • _:代表任意单个字符

    例如:

    1
    2
    3
    select num, color
    from ball
    where name like '%x_';

    则,aaaxbxc 等都会被筛选出来。

  • 如果 like 后面的匹配串中不含通配符,可以用 = 替代

  • 若匹配串中本身自带了 %及 _ 字符,可以用 escape 对其进行转义

    例如:

    1
    where Cname like 'A\_B' eacape '\'

    这段代码的意思是将 \ 设为转义字符,跟在 \ 后面的通配符将被转义为普通字符。此时会寻找对应属性等价于 ‘A_B’ 的元组

查询空值:

1
where 属性 is null

此处的 is 不能够用 = 替代。

因为 “是空的” ,而不是 “等于空”

多重条件查询:

可以通过 and 、or 、not 连接多个条件,进行复杂的查询。

in 可以看作是多个 or 的语法糖。

1
where name in ('zhang', 'li')

等价于

1
where name = 'zhang' or name = 'li'

3. order by

用户可以通过 order by 对查询结果按照一个或多个属性列进行升序 (asc) 或降序 (desc) 排列。(默认为升序)

1
2
3
select 列名
from 表名
order by 排序元组 asc|desc;

4.聚集函数

输入值的集合,返回单个值的函数

(1) count

1
count(*)

统计元组个数

1
count(distinct|all 列名)

统计一列中值的个数

(2) sum

1
sum(distinct|all 列名)

(3) avg

1
avg(distinct|all 列名)

(4) max

1
max(distinct|all 列名)

(5) min

1
min(distinct|all 列名)

(6) 注意

  • 若指定了 distinct ,则会在计算时取消重复值;若没有指定,则默认为 all ,在计算时不取消重复值
  • 当聚集函数遇到空值时,除了 count(*) 以外,都会跳过空值
  • 聚集函数不能用于 where 语句,仅能用于 select 和 group by 中的 having

5.group by

(1) 作用

该语句将查询结果按值分组,需要配合聚集函数使用。

常用用法:

  • 首先按照属性的不同将表分为若干组

  • select 聚焦函数,算出每一组的函数值

  • select 分组字段 用于对聚集函数的结果进行标识

    也可以 select 普通字段 ,会自动将分组中第一条记录的对应值作为结果中的值,但这没有任何意义

(2) 基本语法

1
2
3
select 属性, 聚集函数
from 表名
group by 属性;

(3) 运行结果

1
2
3
属性1  聚焦函数(分组1)
属性2 聚焦函数(分组2)
属性3 聚焦函数(分组3)

(4) having

分组后可以用 having 语句指定筛选条件,满足条件的分组才会被选出来。

where:用于筛选元组,在分组前进行限定

having:用于筛选元组组成的分组,在分组后对分组进行限定

1
2
3
4
select 属性, 聚集函数
from 表名
group by 属性
having 筛选条件;

(5) 示例

数据表:

查询语句:

1
2
3
4
5
6
7
SELECT
sex,
AVG( score )
FROM
students
GROUP BY
sex

查询结果:

二、连接查询

若一个查询同时两个以上的表,则称为连接查询,包括等值连接查询、自然连接查询、非等值连接查询、自身连接查询、外连接查询和复合条件连接查询等。

1.等值和非等值连接

1
where [表名1].列名1 = [表名2].列名2
  • where 语句中用来连接两个表的条件称为连接条件,连接条件中的运算符称为连接运算符。
  • 当连接运算符为 = 时,称为等值连接;使用其它运算符时称为非等值连接。
  • 连接条件中的两边必须具有可比性
  • 可以在属性名前面加上表名前缀,防止产生混淆

例如:

将学生和课程进行等值连接查询,组成选课情况表。

1
2
3
select Student.*, SC.*
from Student, SC
where Student.Sno = SC.Sno;

2.自然连接

在等值连接中,把目标列中重复的属性列去掉,就是自然连接。

等值连接:选择两个关系中对应属性相等的元组,拼在一起

自然连接:对等值连接结果做一次投影,相同的属性只保留一份

3.自身连接

一个表与自身的连接,称为自身连接。

例如:

要将同一个表连接起来,首先应该为两个表分别起一个别名,然后进行连接。

1
2
3
select First.Cno, SECOND.Cpno
from Course First, Course SECOND
where FIRST.Cpno = SECOND.Cno;

4.外连接

将两个表进行连接操作时,在另外一个表中没有对应元组的元组也加入到查询结果中,空缺的部分用 null 填补。若保留左边,则称为左外连接;保留右边,则称为右外连接。

例如:

1
2
select Student.Sno, Sname, Ssex, Sage, Cno, Grade
form Student left outer join SC on (Student.Sno = SC.Sno)

5.多表连接

连接操作还可以同时连接多个表。

三、嵌套查询

在 SQL 语言中,一个 select - from - where 称为一个查询块。将一个查询块嵌套在另一个查询块的 where 或 having 中的查询称为 嵌套查询

例如:

1
2
3
4
5
6
select Sname
from Student
where Sno in
(select Sno
from SC
where Cno = '2');

在此例中,上层查询块被称为外层查询父查询,下层查询块被称为内层查询子查询

  • SQL 语言允许多层嵌套查询,即一个子查询中还可以嵌套其它子查询。
  • 子查询中不能使用 order by ,因为对非最终结果的排序是无意义的
  • 嵌套查询使用户能够用多个简单查询构成复杂的查询

1. 筛选-判断是否在集合中

如果子查询的结果是一个集合,那么可以用 in 或 not in 筛选元组。

2.筛选-与值比较

当用户明确知道子查询返回的是单个值时,可以用 > 、< 、= 等比较运算符。

3.筛选-与集合比较

若子查询返回集合,且需要进行比较查询,便可以使用 any 和 all 。其中, any 指任意, all 指所有。

4.用 exists 判断是否存在

带有 exists 的子查询不返回任何数据,只返回 true 和 false 。

例如:

由 exists 引出的子循环,其目标列表达式通常都用 * ,因为查询只返回布尔值,给出列名无实际意义。

四、集合查询

即通过“并 union ”、“交 intersect ”和“差 except ”,对多个 select 的结果进行集合运算。

1
select-from-where union|intersect|except select-from-where;

五、基于派生表的查询

子查询不仅可以出现在 where 中,也可以出现在 from 中,此时子查询会生成临时派生表,作为主查询的查询对象。

需要注意,基于派生表的查询需要为派生表指定别名。

参考

  • 数据库系统概论