sql语句执行步骤详解
2019-12-03 16:01
目录
一、准备工作
二、SQL逻辑查询语句执行顺序
三、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)