SQL解析顺序

示例: 

SELECT DISTINCT 
    < select_list >
FROM
    < left_table > < join_type > 
JOIN < right_table > ON < join_condition > 
WHERE
    < where_condition > 
GROUP BY 
    < group_by_list > 
HAVING
    < having_condition > 
ORDER BY 
    < order_by_condition > 
LIMIT 
    < limit_number >

执行顺序如图:

-- 行过滤
1 FROM <left_table> 
2 ON <join_condition> 
3 <join_type> JOIN <right_table> 第二步和第三步会循环执行 
4 WHERE <where_condition> 第四步会循环执行,多个条件的执行顺序是从左往右的。 
5 GROUP BY <group_by_list> 
6 HAVING <having_condition> --列过滤 
7 SELECT 分组之后才会执行SELECT 
8 DISTINCT <select_list> --排序 
9 ORDER BY <order_by_condition> -- MySQL附加 
10 LIMIT <limit_number> 前9步都是SQL92标准语法。limit是MySQL的独有语法。

首先,造几条数据作为测试

CREATE TABLE product ( pid INT PRIMARY KEY AUTO_INCREMENT,   
  pname VARCHAR(20), 
  price DOUBLE,  
  pdate DATE,  
  cid int  
); 
create table category( id INT PRIMARY KEY , cname varchar(100) );
 
INSERT INTO product VALUES(NULL,'泰国大榴莲', 98, NULL, 1); 
INSERT INTO product VALUES(NULL,'泰国大枣', 38, NULL, 1); 
INSERT INTO product VALUES(NULL,'新疆切糕', 68, NULL, 2); 
INSERT INTO product VALUES(NULL,'十三香', 10, NULL, 2); 
INSERT INTO product VALUES(NULL,'泰国大枣', 20, NULL, 2);
insert into product values(null,'泰国大枣',98,null,20);  
insert into product values(null,'iPhone手机',800,null,30); 

INSERT INTO category VALUES(1,'国外食品'); 
INSERT INTO category VALUES(2,'国内食品'); 
INSERT INTO category VALUES(3,'国内服装');  

现在开始SQL解析之旅吧!

1.FROM

对FROM的左边的表和右边的表计算(笛卡尔积),产生虚表VT1

select * from product,category;

2.ON过滤

对虚表VT1进行ON筛选,只有符合记录的才会被记录在虚表VT2中。

 select * from product a , category b where a.cid=b.id;

这里因为语法限制,使用了where 代替。

3.OUTER JOIN添加外部列

如果指定了outer join(比如left join,right join)那么保留表中未匹配的行就会作为外部行添加到虚拟VT2表中,产生虚拟表VT3。

如果FROM子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行1-3这三个步骤,一直到处理完所有的表为止。

select * from product a left outer join category b on a.cid=b.id;

select * from product a right outer join category b on a.cid=b.id;

4.WHERE

对虚拟表VT3进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4中。

注意此时因为分组,不能使用聚合运算;也不能使用SELECT中创建的别名

与ON的区别:

如果有外部列,ON针对过滤的是关联表,主表(保留表)会返回所有的列;

如果没有添加外部列,两者的效果是一样的;

应用:
对主表的过滤应该放在 WHERE
对于关联表,先条件查询后连接则用 ON ,先连接后条件查询则用 WHERE
 select * from product a left outer join category b on a.cid=b.id where a.pname='泰国大枣';

 

5.GROUP BY

根据group by子句中的列,对VT4中的记录进行分组操作,产生虚拟表VT5.

注意其后处理过程的语句,如SELECT,HAVING,所用到的列必须包含在GROUP BY中。对于没有出现的,得用聚合函数;

原因GROUP BY改变了对表的引用,将其转换为新的引用方式,能够对其进行下一级逻辑操作的列会减少。

 select * from product a left outer join category b on a.cid=b.id where a.pname='泰国大枣' group by a.price;

可以看到,如果用以上的sq会出现错误,我们将sql进行修改一下。

 select a.price from product a left outer join category b on a.cid=b.id where a.pname='泰国大枣' group by a.price;

这样就可以查询到数据了。

6.HAVING

对虚拟表VT5 应用having过滤,只有符合的记录才会被 插入到 虚拟表VT6 中。

select a.PRICE,b.ID from product a left outer join category b on a.cid=b.id where a.pname='泰国大枣' group by a.price,b.id having b.id <=2;

7.SELECT

这个子句对SELECT子句中的元素进行处理,生成VT5表。

8.DISTINCT

寻找VT5-1中的重复列,并删掉,生成VT5-J2

select distinct a.pname from product a left outer join category b on a.cid=b.id where a.pname='泰国大枣' group by a.price ;

9.ORDER BY

VT5-J2 中的表中,根据ORDER BY 子句的条件对结果进行排序,生成VT6表。

10.LIMIT(MySQL特有)

LIMIT子句从上一步得到的 VT6虚拟表 中选出从指定位置开始的指定行数据。

解析顺序总结:

WHERE条件解析顺序:

1. MySQL :从左往右去执行 WHERE 条件的。

2. Oracle :从右往左去执行 WHERE 条件的。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值