sql语句执行步骤详解


一、准备工作

先来一段伪代码,首先你能看懂么?

SELECT DISTINCT 
	FROM 
	 JOIN 
	ON 
	WHERE 
	GROUP BY 
	HAVING 
	ORDER BY 
	LIMIT 

继续做以下的前期准备工作:

新建一个测试数据库TestDB;

create database TestDB;

创建测试表table1和table2;

 CREATE TABLE table1
 (
     customer_id VARCHAR(10) NOT NULL,
     city VARCHAR(10) NOT NULL,
     PRIMARY KEY(customer_id)
 )ENGINE=INNODB DEFAULT CHARSET=UTF8;
 
 CREATE TABLE table2
 (
     order_id INT NOT NULL auto_increment,
     customer_id VARCHAR(10),
     PRIMARY KEY(order_id)
 )ENGINE=INNODB DEFAULT CHARSET=UTF8;

插入测试数据;

 INSERT INTO table1(customer_id,city) VALUES('163','hangzhou');
 INSERT INTO table1(customer_id,city) VALUES('9you','shanghai');
 INSERT INTO table1(customer_id,city) VALUES('tx','hangzhou');
 INSERT INTO table1(customer_id,city) VALUES('baidu','hangzhou');
 
 INSERT INTO table2(customer_id) VALUES('163');
 INSERT INTO table2(customer_id) VALUES('163');
 INSERT INTO table2(customer_id) VALUES('9you');
 INSERT INTO table2(customer_id) VALUES('9you');
 INSERT INTO table2(customer_id) VALUES('9you');
 INSERT INTO table2(customer_id) VALUES('tx');
 INSERT INTO table2(customer_id) VALUES(NULL);

准备工作做完以后,table1和table2看起来应该像下面这样:

	 mysql> select * from table1;
	 +-------------+----------+
	 | customer_id | city     |
	 +-------------+----------+
	 | 163         | hangzhou |
	 | 9you        | shanghai |
	 | baidu       | hangzhou |
	 | tx          | hangzhou |
	 +-------------+----------+
	 4 rows in set (0.00 sec)
 mysql> select * from table2;
 +----------+-------------+
 | order_id | customer_id |
 +----------+-------------+
 |        1 | 163         |
 |        2 | 163         |
 |        3 | 9you        |
 |        4 | 9you        |
 |        5 | 9you        |
 |        6 | tx          |
 |        7 | NULL        |
 +----------+-------------+
 7 rows in set (0.00 sec)

准备SQL逻辑查询测试语句

	 SELECT a.customer_id, COUNT(b.order_id) as total_orders
	 FROM table1 AS a
	 LEFT JOIN table2 AS b
	 ON a.customer_id = b.customer_id
	 WHERE a.city = 'hangzhou'
	 GROUP BY a.customer_id
	 HAVING count(b.order_id) < 2
	 ORDER BY total_orders DESC;

使用上述SQL查询语句来获得来自杭州,并且订单数少于2的客户。

二、SQL逻辑查询语句执行顺序

还记得上面给出的那一长串的SQL逻辑查询规则么?那么,到底哪个先执行,哪个后执行呢?现在,我先给出一个查询语句的执行顺序:

	(7) SELECT /* 处理SELECT列表,产生 VT7 */
	(8) DISTINCT  /* 将重复的行从 VT7 中删除,产品 VT8 */
	(1) FROM   /* 对FROM子句中的表执行笛卡尔积(交叉联接),生成虚拟表 VT1。 */
	(3)  JOIN  /* 如果指定了OUTER JOIN(相对于CROSS JOIN或INNER JOIN),
	  保留表中未找到匹配的行将作为外部行添加到 VT2,生成 VT3。
	  如果FROM子句包含两个以上的表,
	  则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,
	  直到处理完所有的表位置。   */
	(2) ON /* 对 VT1 应用 ON 筛选器,只有那些使为真才被插入到 VT2。 */
	(4) WHERE /* 对 VT3 应用 WHERE 筛选器,只有使为true的行才插入VT4。 */
	(5) GROUP BY    /* 按 GROUP BY子句中的列列表对 VT4 中的行进行分组,生成 VT5 */
	(6) HAVING   /* 对 VT5 应用 HAVING 筛选器,只有使为true的组插入到 VT6 */
	(9) ORDER BY   /* 将 VT8 中的行按 ORDER BY子句中的列列表顺序,生成一个游标(VC10),
	  生成表TV11,并返回给调用者。 */
	(10)LIMIT 

Oracle SQL语句执行顺序

	(8)SELECT (9)DISTINCT  (11)