示例:
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 条件的。