透过商品订单了解MySQL视图

303 阅读4分钟

本文正在参加「技术专题19期 漫谈数据库技术」活动

视图是sql当中的一个很重要的知识点,本身难度并不高,但是,什么时候使用,一直让人很困惑,因为视图其实会影响到查询的效率,那么我们通过用户,商品和订单来聊聊MySQL的视图的使用场景。

场景

一个电商平台,每天要有很多笔交易,离不开两个个业务主体,就是商品,订单。除了常规的业务查询之外,电商平台都会基于运营需求去统计商品的销售情况,为店铺的成长或者平台规划提供依据,我们以订单表为核心来聊一聊视图,首先看一下表结构:

(当然,这里只是为了展示视图功能,表结构做了简化)

mysql> desc goods;
+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| id           | int(11)      | NO   | PRI | NULL    | auto_increment |
| goods_name   | varchar(32)  | YES  |     | NULL    |                |  #商品名称
| count        | int(11)      | YES  |     | NULL    |                |  #商品数量
| goods_price  | float        | YES  |     | NULL    |                |  #商品价格
| origin_place | varchar(200) | YES  |     | NULL    |                |  #生产场地
| origin_time  | varchar(20)  | YES  |     | NULL    |                |  #生产日期
+--------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
​
mysql> desc order_info;
+------------------+-------------+------+-----+---------+----------------+
| Field            | Type        | Null | Key | Default | Extra          |
+------------------+-------------+------+-----+---------+----------------+
| id               | int(11)     | NO   | PRI | NULL    | auto_increment |
| consignee        | varchar(32) | YES  |     | NULL    |                | #收货人
| consignee_phone  | varchar(14) | YES  |     | NULL    |                | #收货人电话
| total_amount     | float       | YES  |     | NULL    |                | #订单总价格
| order_status     | int(11)     | YES  |     | NULL    |                | #订单状态
| user_id          | int(11)     | YES  |     | NULL    |                | #用户id
| goods_id         | int(11)     | YES  |     | NULL    |                | #商品id
| store_id         | int(11)     | YES  |     | NULL    |                | #店铺id
| payment_way      | int(11)     | YES  |     | NULL    |                | #支付方式
| delivery_address | text        | YES  |     | NULL    |                | #送货地址
| order_comment    | text        | YES  |     | NULL    |                | #订单备注
| create_time      | varchar(20) | YES  |     | NULL    |                | #创建时间
| parent_order_id  | int(11)     | YES  |     | NULL    |                | #父订单编号
| feight_fee       | float       | YES  |     | NULL    |                | #运费
+------------------+-------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)

上面是表结构,下面来看一下业务需求吧,每个月生产一封关于平台的订单报表:

包括订单量最高的三种商品,

每天订单的数量

每天订单创建的时间分布

等等

视图

结合上面的需求来聊聊视图:

1、视图是虚表,没有行,也没有列,更没有数据,只是通过一个查询语句构建的虚拟的表结构,具有和真实表类似的功能,但是每次使用视图,都会执行构建虚表的查询语句,所以查询的速度比较慢,我们查询一个商品的订单量,首先是一个复杂的嵌套查询,本身编写起来比较复杂,而且每个月查询一次,对查询效率的要求也不高,那么在这种场景下,使用视图先构建出来一个契合业务的表,然后基于这个表查询会方便很多。

2、视图本身是基于其他表的查询,所以可以用视图作为隔离,返回一张过滤后的表,这样对数据安全也是有好处的,订单表本身含有的信息比较多,在上面的这个需求当中实际上使用到的订单表的字段并不多,或者说只是数量统计,那么这个时候采用视图表,访问视图表会和原来的订单表和商品表形成隔离,也有了一定的安全意义。

3、在业务层面数据展示的过程当中,比如对时间的格式等字段都是有特殊要求的,如果直接查询,那么到了服务端或者前端渲染不得不从新循环数据,对数据的格式进行修改,但是使用视图就可以在构建表的时候,调整数据格式来配合业务需求,方便服务的和前端的使用。

4、还有一个点,基于sql语句的编写,视图更像是编程过程当中的函数,提高了代码的复用程度,便于sql语句的维护。

所以可以构建这样的一个视图来复用嵌套查询:

create view goods_order as 
select 
    goods_name,
    (select count(*) from order_info where order_info.goods_id = goods.id) as order_number 
from goods order by order_number desc limit 5;
​
mysql> select * from goods_order;
+------------+--------------+
| goods_name | order_number |
+------------+--------------+
| 超级奶茶1   |           999 |
| 超级奶茶2   |           888 |
| 超级奶茶3   |           777 |
| 超级奶茶4   |           666 |
| 超级奶茶5   |           555 |
+------------+--------------+
1 row in set (0.00 sec)

或者这样修改查询的结构格式

create view goods_comment as
select concat(goods.goods_name,"(",order_info.order_comment,")") as  goods_comment from goods,order_info where order_info.goods_id = goods.id;
​
mysql> select * from goods_comment;
+----------------------+
| goods_comment        |
+----------------------+
| 超级奶茶(加糖不加冰) |
| 超级奶茶(加冰不加糖) |
+----------------------+
2 rows in set (0.01 sec)

所以基于上面再看视图,是不是有所了解了,今天就先聊这么多,还请大家多多指点呀。

本文正在参加「技术专题19期 漫谈数据库技术」活动