网站分成比例系统怎么做,中国黄页网官网,做面包的公司网站,开发公司购买的游乐设备计入什么科目SQL语句的解析顺序 文章目录 SQL语句的解析顺序编写顺序与解析顺序解析顺序关键字FROMONOUTER JOINWHEREGROUP BYHAVINGSELECTDISTINCTORDER BYLIMIT 解析流程流程分析流程说明WHERE条件解析顺序 编写顺序与解析顺序
编写顺序
SELECT DISTINCTselect_list
FROMselect_list
FROMleft_table join_type
JOIN right_table ON join_condition
WHEREwhere_condition
GROUP BYgroup_by_list
HAVINGhaving_condition
ORDER BYorder_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的独有语法。解析顺序关键字
FROM
对FROM的左边的表和右边的表计算 笛卡尔积(CROSS JOIN) 。产生虚表VT1
mysql select * from product,category;
------------------------------------------------------------
| pid | pname | price | pdate | cid | id | cname |
------------------------------------------------------------
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 1 | 国外食品 |
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 2 | 国内食品 |
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 3 | 国内服装 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 2 | 国内食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 3 | 国内服装 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 1 | 国外食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 2 | 国内食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 3 | 国内服装 |
| 4 | 十三香 | 10 | NULL | 2 | 1 | 国外食品 |
| 4 | 十三香 | 10 | NULL | 2 | 2 | 国内食品 |
| 4 | 十三香 | 10 | NULL | 2 | 3 | 国内服装 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 1 | 国外食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 3 | 国内服装 |
| 6 | 泰国大枣 | 98 | NULL | 20 | 1 | 国外食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | 2 | 国内食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | 3 | 国内服装 |
| 7 | iPhone手机 | 800 | NULL | 30 | 1 | 国外食品 |
| 7 | iPhone手机 | 800 | NULL | 30 | 2 | 国内食品 |
| 7 | iPhone手机 | 800 | NULL | 30 | 3 | 国内服装 |
------------------------------------------------------------
21 rows in set (0.00 sec)通过在 FROM 子句中列出多个表格你可以执行一个叫做交叉连接Cross Join的操作它会将product,category两个表的每一行进行组合生成一个包含所有可能组合的结果集。 ON
对虚表VT1进行ON筛选只有那些符合的行才会被记录在虚表VT2中
mysql select * from product a, category b where a.cidb.id;
------------------------------------------------------------
| pid | pname | price | pdate | cid | id | cname |
------------------------------------------------------------
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 1 | 国外食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 2 | 国内食品 |
| 4 | 十三香 | 10 | NULL | 2 | 2 | 国内食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
------------------------------------------------------------
5 rows in set (0.00 sec)OUTER JOIN
如果指定了 OUTER JOIN比如left join、 right join 那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2 中产生虚拟表VT3如果FROM子句中包含两个以上的表的话那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤一直到处理完所有的表为止以左表数据为准
mysql select * from product a left outer join category b on a.cidb.id;
--------------------------------------------------------------
| pid | pname | price | pdate | cid | id | cname |
--------------------------------------------------------------
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 1 | 国外食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 2 | 国内食品 |
| 4 | 十三香 | 10 | NULL | 2 | 2 | 国内食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | NULL | NULL |
| 7 | iPhone手机 | 800 | NULL | 30 | NULL | NULL |
--------------------------------------------------------------
7 rows in set (0.00 sec)以右表数据为准
mysql select * from product a right outer join category b on a.cidb.id;
-------------------------------------------------------------
| pid | pname | price | pdate | cid | id | cname |
-------------------------------------------------------------
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 1 | 国外食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 2 | 国内食品 |
| 4 | 十三香 | 10 | NULL | 2 | 2 | 国内食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| NULL | NULL | NULL | NULL | NULL | 3 | 国内服装 |
-------------------------------------------------------------
6 rows in set (0.00 sec)WHERE
对虚拟表VT3 进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4 中 此时因为分组不能使用聚合运算也不能使用SELECT中创建的别名 与ON的区别 如果有外部列ON针对过滤的是关联表主表保留表会返回所有的列如果没有添加外部列两者的效果是一样的 应用 对主表的过滤应该放在WHERE对于关联表先条件查询后连接则用ON先连接后条件查询则用WHERE
mysql select * from product a left outer join category b on a.cidb.id where
a.pname泰国大枣;
-----------------------------------------------------------
| pid | pname | price | pdate | cid | id | cname |
-----------------------------------------------------------
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | NULL | NULL |
-----------------------------------------------------------
3 rows in set (0.00 sec)GROUP BY
根据group by子句中的列对VT4中的记录进行分组操作产生虚拟表VT5。 注意其后处理过程的语句如SELECT,HAVING所用到的列必须包含在GROUP BY中。对于没有出现的得用聚合函数 原因 GROUP BY改变了对表的引用将其转换为新的引用方式能够对其进行下一级逻辑操作的列会减少 理解 根据分组字段将具有相同分组字段的记录归并成一条记录因为每一个分组只能返回一条记录除非是被过滤掉了而不在分组字段里面的字段可能会有多个值多个值是无法放进一条记录的所以必须通过聚合函数将这些具有多值的列转换成单值
mysql select * from product a left outer join category b on a.cidb.id where
a.pname泰国大枣 group by a.price;
-----------------------------------------------------------
| pid | pname | price | pdate | cid | id | cname |
-----------------------------------------------------------
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | NULL | NULL |
-----------------------------------------------------------
3 rows in set (0.01 sec)HAVING
对虚拟表VT5 应用having过滤只有符合的记录才会被插入到虚拟表VT6 中。
mysql select * from product a left outer join category b on a.cidb.id where
a.pname泰国大枣 group by a.price having b.id 2;
-----------------------------------------------------------
| pid | pname | price | pdate | cid | id | cname |
-----------------------------------------------------------
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
-----------------------------------------------------------
2 rows in set (0.00 sec)SELECT
这个子句对SELECT子句中的元素进行处理生成VT5表。(5-J1)计算表达式计算SELECT 子句中的表达式生成VT5-J1
DISTINCT
寻找VT5-1中的重复列并删掉生成VT5-J2如果在查询中指定了DISTINCT子句则会创建一张内存临时表如果内存放不下就需要存放在硬盘了。这张临时表的表结构和上一步产生的虚拟表VT5是一样的不同的是对进行DISTINCT操作的列增 加了一个唯一索引以此来除重复数据。
mysql select distinct a.pname from product a left outer join category b on
a.cidb.id where a.pname泰国大枣 group by a.price ;
--------------
| pname |
--------------
| 泰国大枣 |
--------------
1 row in set (0.00 sec)ORDER BY
从 VT5-J2 中的表中根据ORDER BY 子句的条件对结果进行排序生成VT6表 唯一可使用SELECT中别名的地方 mysql select * from product a left outer join category b on a.cidb.id where
a.pname泰国大枣 group by a.price having b.id 2 order by b.id;
-----------------------------------------------------------
| pid | pname | price | pdate | cid | id | cname |
-----------------------------------------------------------
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
-----------------------------------------------------------
2 rows in set (0.00 sec)LIMIT
LIMIT子句从上一步得到的 VT6虚拟表 中选出从指定位置开始的指定行数据 MySQL特有 offset 和 rows 的正负带来的影响 当偏移量很大时效率是很低的可以这么做 采用子查询的方式优化 在子查询里先从索引获取到最大id然后倒序排再取N行结果集采用INNER JOIN优化 JOIN子句里也优先从索引获取ID列表然后直接关联查询获得最终结果
mysql select * from product a left outer join category b on a.cidb.id where
a.pname泰国大枣 group by a.price having b.id 2 order by b.id limit 1;
----------------------------------------
-------------------
| pid | pname | price | pdate | cid | id | cname |
-----------------------------------------------------------
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
-----------------------------------------------------------
1 row in set (0.00 sec)解析流程 流程分析 FROM将最近的两张表进行笛卡尔积—VT1 ON将VT1按照它的条件进行过滤—VT2 LEFT JOIN保留左表的记录—VT3 WHERE过滤VT3中的记录–VT4…VTn GROUP BY对VT4的记录进行分组—VT5 HAVING对VT5中的记录进行过滤—VT6 SELECT对VT6中的记录选取指定的列–VT7 ORDER BY对VT7的记录进行排序–VT8 LIMIT对排序之后的值进行分页–MySQL特有的语法
流程说明
单表查询根据 WHERE 条件过滤表中的记录形成中间表这个中间表对用户是不可见的然后根据 SELECT 的选择列选择相应的列进行返回最终结果。两表连接查询对两表求积笛卡尔积并用 ON 条件和连接类型进行过滤形成中间表然后根据WHERE条件过滤中间表的记录并根据 SELECT 指定的列返回查询结果。 笛卡尔积行相乘、列相加。 多表连接查询先对第一个和第二个表按照两表连接做查询然后用查询结果和第三个表做连接查询以此类推直到所有的表都连接上为止最终形成一个中间的结果表然后根据WHERE条件过滤中间表的记录并根据SELECT指定的列返回查询结果。
WHERE条件解析顺序
MySQL 从左往右去执行 WHERE 条件的。Oracle 从右往左去执行 WHERE 条件的。 写WHERE条件的时候优先级高的部分要去编写过滤力度最大的条件语句