视图包含聚合函数 查询慢_SQL高级查询(一)

高级查询可以让我们的SQL语句更加灵活,完成更多的任务需求。

1 视图


什么是视图?简单的说,视图就是一张临时表,它并不保存实际的数据,保存的只是select语句而已。比如我们在数据库中创建了很多表,这些表都是被保存在电脑的硬盘中,是真实存在的。而视图好似这些数据的“镜像”,它是镜中月,水中花,只是一些可以让你查询到数据的语句,并不是数据本身。

说了这么多,那视图有什么优点呢?首先肯定就是节省存储空间了,毕竟select语句比实际数据要节省不只一个量级的空间。其次,可以对经常使用的select语句创建视图,以后就不用重复书写,直接调用视图就可以了。最后,视图会跟随原表数据自动更新,保持数据的新鲜性。

创建视图的语句格式:

create view 视图名(视图列名1,视图列名2,...)

as

select语句;

其中的as必不可少,并且select语句的列名和视图的列名顺序是完全一致的。举个栗子,还是用shell数据库中的cargo表:

7e9a2ef79660351241c52529a02e8d54.png

我们创建了一个名为type_amount的视图,视图的列名分别是type和quantity。创建之后,就可以查看我们的视图了:

ec0f9ef74ad40c6cbaa1f14c8f04d0d5.png

如果我们经常需要这个表,就可以把它保存为视图,节省空间。

需要注意的有2点:

  1. 在定义视图时,不能使用order by子句。(只有PostgreSQL可以)
  2. 删除视图时,可以使用如下语句:
  3. drop view 视图名;

2 子查询


什么是子查询?简单的说,子查询就是一次性的视图。换句话说,它并不会像视图一样保存在硬盘中(视图保存的是语句,并不是不保存),而是在执行完后就自动消失了。再直接点说,子查询就是把用来定义视图的select语句直接写在了from子句后面,相当于在from子句中又嵌套了一个select语句。我们可以把上个例子中的视图type_amount转换为以下的select语句:

85a85425aceac85f2cf77d6ecd20f593.png

可以看到,与之前的结果完全相同。在上述语句中,先执行括号内的select语句,再执行外层的select语句。在实际应用中,应尽量避免使用多层嵌套,不仅不易理解,还会拖慢运行速度。

下面我们来看另一种形式的子查询:标量子查询。

标量就是数值,标量子查询就是返回结果是单一值的子查询。那返回结果什么时候是单一值呢?一般聚合函数的返回值都是单一值,比如我们可以在where子句中使用标量子查询:

27ee0b05f6b280936d2423c51dbacf6b.png

如上图,我们选出了售价大于平均价格的商品类型。where子句中不能使用聚合函数,因此如果写成

where sale_price > avg(sale_price)

则会报错。

标量子查询可以出现在任何使用常数或者列名的地方,但其只能返回单行单列的结果。

上图我们是对所有行进行比较,如果我们想要知道每个商品类型中大于平均价格的商品呢?也就是说,我们要对分组后的结果再进行一次比较。如果在where子句中直接写:

where sale_price > (select avg(sale_price) from cargo

group by type);

则会报错,因为括号内并不是标量子查询,它返回多行值,只是一般的子查询。

这里我们就需要用关联子查询了:

a684fea4e5cb1b579ef2078316397932.png

可以看到,我们在原来子查询后加了一条where子句:

where a1.type = a2.type;

这个子句的含义是,在相同的商品种类中,对售价与均价进行比较。由于是同一张表cargo,我们将其分别命名为a1和a2。其实就相当于把cargo表又复制了一份,一份是原表,一份是按type类求平均值的表。然后将这两张表按照类型来进行比较,等于是按类型划分的标量子查询。

最后要注意的就是,关联的条件一定要写在子查询中。如果写在外部,由于执行顺序是由内到外,内层的子查询执行后只会留下一个均值的结果,我们命名的a2表就会消失。在外层找不到a2表,自然会报错。牢记,子查询只是一次性的视图,执行完后就会消失。

SQL的高级查询还有很多内容,我们下篇再见。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值