MySQL查询处理过程分析

MySQL查询处理过程分析

介绍

查询操作是关系型数据库中使用最为频繁的操作,也是构成其它SQL语句(如:Delete、Update)的基础。

要删除或更新某些记录时,首先要查询出这些记录,然后对其进行相应的操作。

查询处理

SQL语言不同于其它编程语言(C、Java等),最明显的不同体现在其处理代码顺序上。

在SQL语句中,第一个被处理的字句总是from字句。

举例

(8)SELECT (9)DISTINCT<select_list>
(1)FROM table1
(3)JOIN table2..
(2)ON   <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)WITH{cube|rollup}
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>
(11)LIMIT <limit_numer>

备注:查询执行顺序如上

1、from:对from字句中的左表和右表执行笛卡儿积,产生虚表VT1
2、on:对虚表VT1进行on筛选,只选取符合条件的记录作为虚表VT2
3、join:如果指定了outer join(如left outer join、right outer join)那么保留表中未匹配的行为作为外部行添加到虚拟表VT2中, 
产生虚拟表VT3.如果from字句包含两个以上表,则对上一个连接生成的结果表VT3和下一个表重复执行步骤1和步骤3,
直到处理完所有表为止。
4、where:对虚拟表VT3应用where过滤条件,筛选符合记录保存到虚拟表VT4
5、group by:根据group by 字句中的列,对VT4中的记录进行分组操作,产生虚拟表VT5
6、cube|rollup:对标VT5进行cube或rollup操作产生虚拟表VT6
7、对虚拟表VT6进行having过滤,筛选符合条件的记录到虚拟表VT7
8、select:第二次执行select操作,选定指定的列到虚拟表VT8中
9、distinct:去除重复数据,产生虚拟表VT9
10、order by:将虚拟表VT9按照排序字段进行排序操作,产生虚拟表VT10
11、limit:取出指定行数的记录,产生虚拟表VT11,即最终呈现给用户的表。

案例展示

客户表:
DROP TABLE IF EXISTS `customers`;
CREATE TABLE `customers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `customer_id` int(11) NOT NULL,
  `city` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of customers
-- ----------------------------
INSERT INTO `customers` VALUES ('1', '1', '成都');
INSERT INTO `customers` VALUES ('2', '2', '杭州');
INSERT INTO `customers` VALUES ('3', '3', '上海');
INSERT INTO `customers` VALUES ('4', '4', '北京');

订单表:
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL,
  `customer_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of orders
-- ----------------------------
INSERT INTO `orders` VALUES ('1', '1', '3');
INSERT INTO `orders` VALUES ('2', '2', '1');
INSERT INTO `orders` VALUES ('3', '3', '3');
INSERT INTO `orders` VALUES ('4', '4', '2');
INSERT INTO `orders` VALUES ('5', '5', '4');

查询订单数不小于2且用户是上海的用户信息?

SELECT customers.customer_id,COUNT(orders.order_id) AS order_num
FROM customers LEFT JOIN orders
ON customers.customer_id=orders.customer_id
WHERE customers.city="上海"
GROUP BY customers.customer_id
HAVING COUNT(orders.order_id)>=2
ORDER BY order_num
LIMIT 100;

备注:即使再复杂的SQL语句都是由简单的SQL拼接出来的,所以写SQL语句时,可以一边写一边执行分析。

GROUP BY … HAVING …

GROUP BY ... HAVING ... 字句应该是这些当中比较难使用的筛选条件了

其使用原则:TODO

...

总结

复杂的SQL都是可以拆分成多条简单SQL的,所以写复杂SQL时要一步一步分析,一蹴而就比较难,除非你特别熟悉之后。

参考

1、MySQL技术内幕SQL编程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章