SQL高级查询(一)
高级查询可以让我们的SQL语句更加灵活,完成更多的任务需求。
1 视图
什么是视图?简单的说,视图就是一张临时表,它并不保存实际的数据,保存的只是select语句而已。比如我们在数据库中创建了很多表,这些表都是被保存在电脑的硬盘中,是真实存在的。而视图好似这些数据的“镜像”,它是镜中月,水中花,只是一些可以让你查询到数据的语句,并不是数据本身。
说了这么多,那视图有什么优点呢?首先肯定就是节省存储空间了,毕竟select语句比实际数据要节省不只一个量级的空间。其次,可以对经常使用的select语句创建视图,以后就不用重复书写,直接调用视图就可以了。最后,视图会跟随原表数据自动更新,保持数据的新鲜性。
创建视图的语句格式:
create view 视图名(视图列名1,视图列名2,...)
as
select语句;
其中的as必不可少,并且select语句的列名和视图的列名顺序是完全一致的。举个栗子,还是用shell数据库中的cargo表:
我们创建了一个名为type_amount的视图,视图的列名分别是type和quantity。创建之后,就可以查看我们的视图了:
如果我们经常需要这个表,就可以把它保存为视图,节省空间。
需要注意的有2点:
- 在定义视图时,不能使用order by子句。(只有PostgreSQL可以)
- 删除视图时,可以使用如下语句:
- drop view 视图名;
2 子查询
什么是子查询?简单的说,子查询就是一次性的视图。换句话说,它并不会像视图一样保存在硬盘中(视图保存的是语句,并不是不保存),而是在执行完后就自动消失了。再直接点说,子查询就是把用来定义视图的select语句直接写在了from子句后面,相当于在from子句中又嵌套了一个select语句。我们可以把上个例子中的视图type_amount转换为以下的select语句:
可以看到,与之前的结果完全相同。在上述语句中,先执行括号内的select语句,再执行外层的select语句。在实际应用中,应尽量避免使用多层嵌套,不仅不易理解,还会拖慢运行速度。
下面我们来看另一种形式的子查询:标量子查询。
标量就是数值,标量子查询就是返回结果是单一值的子查询。那返回结果什么时候是单一值呢?一般聚合函数的返回值都是单一值,比如我们可以在where子句中使用标量子查询:
如上图,我们选出了售价大于平均价格的商品类型。where子句中不能使用聚合函数,因此如果写成
where sale_price > avg(sale_price)
则会报错。
标量子查询可以出现在任何使用常数或者列名的地方,但其只能返回单行单列的结果。
上图我们是对所有行进行比较,如果我们想要知道每个商品类型中大于平均价格的商品呢?也就是说,我们要对分组后的结果再进行一次比较。如果在where子句中直接写:
where sale_price > (select avg(sale_price) from cargo
group by type);
则会报错,因为括号内并不是标量子查询,它返回多行值,只是一般的子查询。
这里我们就需要用关联子查询了:
可以看到,我们在原来子查询后加了一条where子句:
where a1.type = a2.type;
这个子句的含义是,在相同的商品种类中,对售价与均价进行比较。由于是同一张表cargo,我们将其分别命名为a1和a2。其实就相当于把cargo表又复制了一份,一份是原表,一份是按type类求平均值的表。然后将这两张表按照类型来进行比较,等于是按类型划分的标量子查询。
最后要注意的就是,关联的条件一定要写在子查询中。如果写在外部,由于执行顺序是由内到外,内层的子查询执行后只会留下一个均值的结果,我们命名的a2表就会消失。在外层找不到a2表,自然会报错。牢记,子查询只是一次性的视图,执行完后就会消失。
SQL的高级查询还有很多内容,我们下篇再见。
更多干货内容,欢迎关注今日头条账号“人人都会机器学习”;你也可以搜索知识星球“自学机器学习”,里面也有精彩内容。