SQL基础(七) 视图和子查询

本文总结自《SQL基础教程》

一、视图
(1)通常,我们在创建表时,会通过 INSERT 语句将数据保存到数据库之中,而数据库中的数据实际上会被保存到计算机的存储设备中。因此,我们通过 SELECT 语句查询数据时,实际上就是从存储设备中读取数据,进行各种计算之后,再将结果返回给用户。
使用视图时并不会将数据保存到存储设备之中,而且也不会将数据保存到其他任何地方。实际上视图保存的是 SELECT 语句,从视图中读取数据时,视图会在内部执行该 SELECT 语句并创建出一张临时表。
(2)视图的优点
视图无需保存数据,因此可以节省存储设备的容量。
可以将频繁使用的 SELECT 语句保存成视图,这样就不用每次都重新书写了。
注意:表中存储的是实际数据,而视图中保存的是从表中取出数据所使用的SELECT语句。
(3)创建视图
可以使用 CREATE VIEW 语句创建视图,其基本语法如下图所示:

CREATE VIEW view_name(view_column_1,view_column_2, ……,view_column_n)
AS
<SELECT子句>

注意: SELECT 语句需要书写在 AS 关键字之后。 SELECT 语句中列的排列顺序和视图中列的排列顺序相同,
eg:
以Person1为例:
在这里插入图片描述
创建视图的sql语句为:

CREATE VIEW GRADE_MAX(EDUCATION,MAX_GRADE)
AS
SELECT EDUCATION,MAX(GRADE)
FROM Person1
GROUP BY EDUCATION;

此时,视图GRADE_MAX创建完毕。
(4)视图的使用
视图和表一样,可以书写在SELECT 语句的 FROM 子句之中
eg:

SELECT EDUCATION,MAX_GRADE
FROM GRADE_MAX;

在这里插入图片描述
在 FROM 子句中使用视图的查询,通常有如下两个步骤:
① 首先执行定义视图的 SELECT 语句
② 根据得到的结果,再执行在 FROM 子句中使用视图的 SELECT 语句

注意: 应该尽量避免在视图的基础上创建视图,因为多重视图会降低 SQL 的性能。
(5)视图的限制

① 定义视图时不能使用ORDER BY子句
这是因为视图和表一样, 数据行都是没有顺序的。
② 对视图进行更新
标准 SQL 中规定:如果定义视图的 SELECT 语句能够满足以下条件,那么这个视图就可以被更新:

   SELECT 子句中未使用 DISTINCT
   FROM 子句中只有一张表
   未使用 GROUP BY 子句
   未使用 HAVING 子句

注意:视图和表需要同时进行更新,因此通过汇总得到的视图无法进行更新。
(6)删除视图

可以使用 DROP VIEW 语句来删除视图,其基本语法如下:

DROP VIEW GRADE_MAX(EDUCATION,MAX_GRADE)

二、子查询
(1)子查询的概念

子查询就是一次性视图(SELECT语句)。与视图不同,子查询在SELECT语句执行完毕之后就会消失。
视图并不是用来保存数据的,而是保存读取数据的 SELECT 语句。子查询就是将用来定义视图的SELECT语句直接用于FROM子句当中。
eg:

CREATE VIEW GRADE_MAX(EDUCATION,MAX_GRADE)
AS
SELECT EDUCATION,MAX(GRADE)
FROM Person1
GROUP BY EDUCATION;

SELECT EDUCATION,MAX_GRADE
FROM GRADE_MAX;

能够实现同样功能的子查询的sql代码如下:

SELECT EDUCATION,MAX_GRADE
FROM (SELECT EDUCATION,MAX(GRADE) AS MAX_GRADE
            FROM Person1
            GROUP BY EDUCATION) AS GRADE_MAX;

该 SELECT 语句包含嵌套的结构,首先会执行 FROM 子句中的 SELECT 语句,然后才会执行外层的 SELECT 语句。
在这里插入图片描述
注意:子查询就是将用来定义视图的 SELECT 语句直接用于FROM 子句当中。
(2)子查询的嵌套

虽然子查询的层数原则上没有限制,可以无限嵌套子查询,但是由于随着子查询嵌套层数的增加, SQL 语句会变得越来越难读懂,性能也会越来越差。因此,应尽量避免使用多层嵌套的子查询
(3)子查询的名称
原则上子查询必须设定名称, 为子查询设定名称时需要使用 AS 关键字,该关键字有时也可以省略
(4) 标量子查询
标量子查询就是返回单一值的子查询。标量子查询则有一个特殊的限制,那就是必须而且只能返回 1 行 1列的结果,也就是返回表中某一行的某一列的值。因此标量子查询的返回值可以用在 = 或者 <> 这样需要单一值的比较运算符之中。
eg:
在where子句中使用标量子查询,如果要求出表Person1中GRADE大于等于最大值的记录的ID、NAME、EDUCATION,则代码如下:

SELECT ID,NAME,EDUCATION
FROM Person1
WHERE GRADE>=(SELECT MAX(GRADE)
               FROM Person1);

在这里插入图片描述
(5) 标量子查询的书写位置
**通常任何可以使用单一值的位置都可以使用标量子查询。**具体来说, 能够使用常数或者列名的地方,无论是 SELECT 子句、 GROUP BY 子句、 HAVING 子句,还是ORDER BY 子句,几乎所有的地方都可以使用。
注意:标量子查询必须返回单一值。
三、 关联子查询
(1)普通子查询和关联子查询的区别

eg:
如果要按照EDUCATION的分类来计算GRADE的平均值,若使用以下sql语句则会报错:

SELECT ID,NAME,EDUCATION
FROM Person1
WHERE GRADE>=(SELECT MAX(GRADE)
               FROM Person1
               GROUP BY EDUCATION);

报错的原因在于该sql代码会返回多行数据,并不是标量子查询。此时,可以使用关联子查询获得想要的结果:

SELECT ID,NAME,EDUCATION
FROM Person1 AS P1
WHERE GRADE>=(SELECT MAX(GRADE)
               FROM Person1 AS P2
               WHERE P1.EDUCATION=P2.EDUCATION
               GROUP BY EDUCATION);

在这里插入图片描述
这里起到关键作用的就是在子查询中添加的 WHERE 子句的条件。 在对表中某一部分记录的集合进行比较时,就可以使用关联子查询。
注意:在细分的组内进行比较时,需要使用关联子查询。
(2) 可使用关联子查询对集合进行切分
(3) 结合条件一定要写在子查询中

在这里插入图片描述
如果写在子查询之外,则在关联名称的作用域之外,就会出错。 这是因为子查询内部设定的关联名称,只能在该子查询内部使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值