菜单

SQL语句执行各个

2018年11月18日 - jQuery

# 执行ORDER BY子句

针对虚拟表中之始末仍指定的排列进行排序,然后回来一个新的虚拟表,我们履行测试SQL语句被的ORDER BY total_orders DESC,就见面落以下内容:

+-------------+--------------+
| customer_id | total_orders |
+-------------+--------------+
| tx          |            1 |
| baidu       |            0 |
+-------------+--------------+

可看看就是指向total_orders列进行降序排列的。上述结果碰头蕴藏在VT8受到。

# 添加外部行

立刻无异步只有当连路也OUTER JOIN时不时才发出,如LEFT OUTER JOINRIGHT OUTER JOINFULL OUTER JOIN。在大部之上,我们都是碰头看略掉OUTER要字之,但OUTER表示的即使是他部行的定义。

LEFT OUTER JOIN拿左表记否保留表,得到的结果吗:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
| baidu       | hangzhou |     NULL | NULL        |
+-------------+----------+----------+-------------+

RIGHT OUTER JOIN将右手表记为保留表,得到的结果为:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
| NULL        | NULL     |        7 | NULL        |
+-------------+----------+----------+-------------+

FULL OUTER JOIN拿左右表都当保留表,得到的结果吗:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
| baidu       | hangzhou |     NULL | NULL        |
| NULL        | NULL     |        7 | NULL        |
+-------------+----------+----------+-------------+

填补加外部行的工作就是是以VT2发明底根基及添加保留表中吃滤条件过滤掉的多少,非保留表中之多少为赋予NULL值,最后生成虚拟表VT3。

出于我在准备的测试SQL查询逻辑语句子被行使的是LEFT JOIN,过滤掉了以下就条数据:

| baidu       | hangzhou |     NULL | NULL        |

现行便把这长长的数据增长到VT2阐明中,得到的VT3阐明如下:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
| baidu       | hangzhou |     NULL | NULL        |
+-------------+----------+----------+-------------+

通下去的操作都见面于拖欠VT3表明及展开。

假如您懂每个重要字的意思,作用,如果您还用过的语句,那再好不过了。但是,你了解这些话语,它们的实行顺序你到底楚么?

  SQL
不同为与另编程语言的无限明白特点是处理代码的一一。在运编程语言中,代码按编码顺序为处理,但是在SQL语言中,第一单让处理的子句是FROM子句,尽管SELECT语句第一独冒出,但是几乎总是最后让处理。

事先来同样段伪代码,首先你能看懂么?

预先来同样段子伪代码,首先你可知看懂么?

# 执行WHERE过滤

本着长外部行取得的VT3开展WHERE过滤,只有切合<where_condition>的笔录才见面输出到虚拟表VT4遭受。当我们履行WHERE a.city = 'hangzhou'的时刻,就会获得以下内容,并是虚拟表VT4遭遇:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| tx          | hangzhou |        6 | tx          |
| baidu       | hangzhou |     NULL | NULL        |
+-------------+----------+----------+-------------+

可是在用WHERE子句时,需要留意以下简单沾:

  1. 由数量还并未分组,因此今还未可知在WHERE过滤器中采取where_condition=MIN(col)即看似对分组统计的过滤;
  2. 鉴于还未曾进行排列的选料操作,因此于SELECT中采用列的别名也是不让允许的,如:SELECT city as c FROM t WHERE c='shanghai';凡无允许出现的。

# 执行HAVING过滤

HAVING子句主要与GROUP BY子句配合以,对分组得到的VT5虚拟表进行标准化过滤。当自家尽测试语句被的HAVING count(b.order_id) < 2常常,将获得以下内容:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| baidu       | hangzhou |     NULL | NULL        |
| tx          | hangzhou |        6 | tx          |
+-------------+----------+----------+-------------+

旋即虽是杜撰表VT6。

执行LIMIT子句

LIMIT子句从达成亦然步得到的VT8心虚拟表中选出从指定位置上马之指定行数据。对于没以ORDER
BY的LIMIT子句,得到的结果一律是无序的,所以,很多上,我们且见面看出LIMIT子句会和ORDER
BY子句一起以。

MySQL数据库的LIMIT支持如下形式的精选:

LIMIT n, m

意味着从今第n久记下开始选择m条记录。而博开发人员喜欢使用该语句来缓解分页问题。对于小数码,使用LIMIT子词没有其他问题,当数据量非常可怜之早晚,使用LIMIT n, m是非常低效的。因为LIMIT的建制是每次都是从头开始扫描,如果要从第60万推行开始,读取3漫长数,就得事先扫描定位到60万实施,然后再展开读取,而扫描的进程是一个生低效的经过。所以,对于充分数额处理时,是很有必不可少当应用层建立一定之缓存机制(貌似现在的那个数目处理,都产生缓存哦)。

参照文档:

SQL逻辑查询语句执行顺序

# 执行WHERE过滤

本着长外部行取得的VT3进展WHERE过滤,只有切合<where_condition>的记录才见面输出及虚拟表VT4负。当我们实践WHERE a.city = 'hangzhou'的时节,就会拿走以下内容,并存在虚拟表VT4蒙:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| tx          | hangzhou |        6 | tx          |
| baidu       | hangzhou |     NULL | NULL        |
+-------------+----------+----------+-------------+

可于采取WHERE子句时,需要小心以下简单碰:

  1. 鉴于数量还尚未分组,因此今尚无可知于WHERE过滤器中使where_condition=MIN(col)这看似对分组统计的过滤;
  2. 鉴于还没有进展排的抉择操作,因此当SELECT中采用列的号也是不被允许的,如:SELECT city as c FROM t WHERE c='shanghai';凡是无同意出现的。

# 执行DISTINCT子句

万一在询问中指定了DISTINCT子句,则会创同摆设内存临时表(如果内存放不产,就得寄放于硬盘了)。这张临时表的说明结构及高达一样步产生的杜撰表VT7凡是如出一辙的,不同的凡对准开展DISTINCT操作的排长了一个唯一索引,以这个来除还数据。

鉴于自家之测试SQL语句被连无利用DISTINCT,所以,在拖欠查询中,这同样步不见面扭转一个虚拟表。

# 执行ON过滤

实施完笛卡尔积以后,接着就是开展ON a.customer_id = b.customer_id规格过滤,根据ON遭遇指定的尺码,去丢那些无符合条件的数,得到VT2说明,内容如下:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
+-------------+----------+----------+-------------+

VT2就是是经过ON极筛选之后得的发因此数据,而连下去的操作以当VT2的功底及连续拓展。

# 添加表面行

马上同一步只有在连续路也OUTER JOIN常常才起,如LEFT OUTER JOINRIGHT OUTER JOINFULL OUTER JOIN。在多数的时候,我们还是会看略掉OUTER重点字的,但OUTER表示的尽管是外部行的定义。

LEFT OUTER JOIN把左表记否保留表,得到的结果为:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
| baidu       | hangzhou |     NULL | NULL        |
+-------------+----------+----------+-------------+

RIGHT OUTER JOIN管右表记为保留表,得到的结果吗:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
| NULL        | NULL     |        7 | NULL        |
+-------------+----------+----------+-------------+

FULL OUTER JOIN把左右表都看作保留表,得到的结果为:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
| baidu       | hangzhou |     NULL | NULL        |
| NULL        | NULL     |        7 | NULL        |
+-------------+----------+----------+-------------+

增补加外部行的工作就是是于VT2发明底基础及添加保留表中让滤条件过滤掉的数码,非保留表中之数额被授予NULL值,最后生成虚拟表VT3。

出于我当备的测试SQL查询逻辑语句被采取的凡LEFT JOIN,过滤掉了以下就漫漫数据:

| baidu       | hangzhou |     NULL | NULL        |

现今就算拿当时长达数据增长到VT2阐明中,得到的VT3发明如下:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
| baidu       | hangzhou |     NULL | NULL        |
+-------------+----------+----------+-------------+

接通下去的操作都见面以拖欠VT3表明及开展。

一经您明白每个重要字的意思,作用,如果您还用了的讲话,那再好不过了。但是,你掌握这些言辞,它们的施行顺序你到底楚么?

  SQL
不同为与另外编程语言的不过强烈特点是处理代码的相继。在运编程语言中,代码按编码顺序为处理,但是于SQL语言中,第一独叫拍卖的子句是FROM子句,尽管SELECT语句第一单冒出,但是几乎连接最后被处理。

# 执行FROM语句

以这些SQL语句的行进程中,都见面生出一个虚拟表,用来保存SQL语句之推行结果(这是重大),我本即来跟这个虚拟表的转移,得到最终的询问结果的过程,来分析任何SQL逻辑查询的实践各个和过程。

第一步,执行FROM言。我们第一得掌握最初步于哪个表开始的,这就算是FROM告知我们的。现在发出了<left_table><right_table>片单说明,我们到底由哪个表开,还是打有限独说明进行某种关联下重新开为?它们中间如何发生联系吗?——笛卡尔积

有关什么是笛卡尔积,请自行Google补脑。经过FROM语句对个别单说明执行笛卡尔积,会得到一个虚拟表,暂且叫VT1(vitual
table 1),内容如下:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 9you        | shanghai |        1 | 163         |
| baidu       | hangzhou |        1 | 163         |
| tx          | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        2 | 163         |
| baidu       | hangzhou |        2 | 163         |
| tx          | hangzhou |        2 | 163         |
| 163         | hangzhou |        3 | 9you        |
| 9you        | shanghai |        3 | 9you        |
| baidu       | hangzhou |        3 | 9you        |
| tx          | hangzhou |        3 | 9you        |
| 163         | hangzhou |        4 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| baidu       | hangzhou |        4 | 9you        |
| tx          | hangzhou |        4 | 9you        |
| 163         | hangzhou |        5 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| baidu       | hangzhou |        5 | 9you        |
| tx          | hangzhou |        5 | 9you        |
| 163         | hangzhou |        6 | tx          |
| 9you        | shanghai |        6 | tx          |
| baidu       | hangzhou |        6 | tx          |
| tx          | hangzhou |        6 | tx          |
| 163         | hangzhou |        7 | NULL        |
| 9you        | shanghai |        7 | NULL        |
| baidu       | hangzhou |        7 | NULL        |
| tx          | hangzhou |        7 | NULL        |
+-------------+----------+----------+-------------+

一起有28(table1的笔录条数 *
table2的笔录条数)条记下。这就算是VT1的结果,接下的操作就在VT1的底子及进行。

# SELECT列表

今日才会实施到SELECT子句,不要觉得SELECT子句给形容以首先实施,就是首先单叫实施之。

我们执行测试语句被的SELECT a.customer_id, COUNT(b.order_id) as total_orders,从虚拟表VT6挨选取来我们需要之情节。我们用沾以下内容:

+-------------+--------------+
| customer_id | total_orders |
+-------------+--------------+
| baidu       |            0 |
| tx          |            1 |
+-------------+--------------+

莫,还没有了,这单是编造表VT7。

# 执行ORDER BY子句

对虚拟表中的情仍指定的排进行排序,然后返回一个新的虚拟表,我们实行测试SQL语句被之ORDER BY total_orders DESC,就会获得以下内容:

+-------------+--------------+
| customer_id | total_orders |
+-------------+--------------+
| tx          |            1 |
| baidu       |            0 |
+-------------+--------------+

足见见这是本着total_orders列进行降序排列的。上述结果碰头蕴藏在VT8受到。

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>

备工作

首先声明下,一切测试操作都是于MySQL数据库及完,关于MySQL数据库的局部略操作,请看一下章:

持续举行以下的初期准备干活:

1、新建一个测试数据库TestDB;

 create database TestDB;

2、创建测试表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;

3、插入测试数据;

 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)

4、准备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底客户。

     
每个步骤都见面发出一个虚拟表,该虚拟表被用作下一个手续的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只是最后一步生成的表才会返回
给调用者。如果无以询问中指定某个同子句,将超越了相应的步调。

# 执行GROUP BY分组

GROU BY子句主要是对运用WHERE支行句得到的虚拟表进行分组操作。我们实践测试语句被之GROUP BY a.customer_id,就见面收获以下内容:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| baidu       | hangzhou |     NULL | NULL        |
| tx          | hangzhou |        6 | tx          |
+-------------+----------+----------+-------------+

取的内容会存入虚拟表VT5遭受,此时,我们就算抱了一个VT5虚拟表,接下去的操作都见面以该表上得。

# 执行GROUP BY分组

GROU BY子句主要是针对运用WHERE旁句得到的虚拟表进行分组操作。我们执行测试语句被之GROUP BY a.customer_id,就会见赢得以下内容:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| baidu       | hangzhou |     NULL | NULL        |
| tx          | hangzhou |        6 | tx          |
+-------------+----------+----------+-------------+

得的情会存入虚拟表VT5着,此时,我们不怕获了一个VT5虚拟表,接下的操作都见面于该表上形成。

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>

# 执行FROM语句

当这些SQL语句之履进程遭到,都见面产生一个虚拟表,用来保存SQL语句之行结果(这是重大),我本即来跟这个虚拟表的变通,得到最终的查询结果的历程,来分析任何SQL逻辑查询的施行顺序及经过。

第一步,执行FROM话。我们第一需明白最开头于哪个表开之,这虽是FROM晓我们的。现在时有发生矣<left_table><right_table>区区个说明,我们到底由哪个表开始,还是从区区只说明展开某种关系之后再也起吧?它们中怎么来联系也?——笛卡尔积

至于什么是笛卡尔积,请自行Google补脑。经过FROM语句对片独说明执行笛卡尔积,会拿走一个虚拟表,暂且叫VT1(vitual
table 1),内容如下:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 9you        | shanghai |        1 | 163         |
| baidu       | hangzhou |        1 | 163         |
| tx          | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        2 | 163         |
| baidu       | hangzhou |        2 | 163         |
| tx          | hangzhou |        2 | 163         |
| 163         | hangzhou |        3 | 9you        |
| 9you        | shanghai |        3 | 9you        |
| baidu       | hangzhou |        3 | 9you        |
| tx          | hangzhou |        3 | 9you        |
| 163         | hangzhou |        4 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| baidu       | hangzhou |        4 | 9you        |
| tx          | hangzhou |        4 | 9you        |
| 163         | hangzhou |        5 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| baidu       | hangzhou |        5 | 9you        |
| tx          | hangzhou |        5 | 9you        |
| 163         | hangzhou |        6 | tx          |
| 9you        | shanghai |        6 | tx          |
| baidu       | hangzhou |        6 | tx          |
| tx          | hangzhou |        6 | tx          |
| 163         | hangzhou |        7 | NULL        |
| 9you        | shanghai |        7 | NULL        |
| baidu       | hangzhou |        7 | NULL        |
| tx          | hangzhou |        7 | NULL        |
+-------------+----------+----------+-------------+

共计有28(table1的笔录条数 *
table2的笔录条数)条记下。这便是VT1的结果,接下的操作就于VT1的基本功及进展。

SQL逻辑查询语句执行各个

尚记上面给起之那么同样抬高串的SQL逻辑查询规则也?那么,到底谁先实行,哪个后执行呢?现在,我事先给出一个查询语句之实施各个:

(7)     SELECT 
(8)     DISTINCT <select_list>
(1)     FROM <left_table>
(3)     <join_type> JOIN <right_table>
(2)     ON <join_condition>
(4)     WHERE <where_condition>
(5)     GROUP BY <group_by_list>
(6)     HAVING <having_condition>
(9)     ORDER BY <order_by_condition>
(10)    LIMIT <limit_number>

地方在各级条告句子之前头都标志了执行顺序号,那么各长达查询语句是如何履行之也?

逻辑查询处理阶段简介

图片 1

  1. FROM:针对FROM子句被的前少独说明执行笛卡尔积(Cartesian
    product)(交叉联接),生成虚拟表VT1
  2. ON:对VT1使ON筛选器。只有那些要<join_condition>为真行才被插入VT2。
  3. OUTER(JOIN):如果指定了OUTER JOIN(相对于CROSS JOIN 或(INNER
    JOIN),保留表(preserved
    table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把有限个表都标记为保留表)中莫找到匹配的即将作为外部行添加到
    VT2,生成VT3.万一FROM子句包含两独以上的表,则对达成一个过渡生成的结果说明和下一个表重复执行步骤1及步骤3,直到处理终结所有的表为止。
  4. WHERE:对VT3应用WHERE筛选器。只有使<where_condition>为true的行才被插入VT4.
  5. GROUP BY:比如GROUP BY子句被之列列表对VT4负之行分组,生成VT5.
  6. CUBE|ROLLUP:把超组(Suppergroups)插入VT5,生成VT6.
  7. HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为true的组才会吃插VT7.
  8. SELECT:处理SELECT列表,产生VT8.
  9. DISTINCT:用再次的行从VT8遇移除,产生VT9.
  10. ORDER BY:将VT9饱受之行按ORDER BY
    子句被的列列表排序,生成游标(VC10).
  11. TOP:自VC10之启处于挑指定数量要比重之行,生成表VT11,并返回调用者。

注:

笛卡尔积简单介绍:假设集合A={a, b},集合B={0, 1,
2},则鲜只聚众的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b,
2)}。

步骤10,按ORDER
BY子句被之列列表排序上步返回的实施,返回游标VC10.随即无异步是率先步也是绝无仅有一步可动用SELECT列表中的列别名的步子。这同样步不同为任何步骤的
是,它不回来有效之说明,而是回到一个游标。SQL是基于集合理论的。集合不会见事先对它们的行排序,它只是成员的逻辑集合,成员的各个无关紧要。对表进行破除序
的查询好回去一个对象,包含本一定物理顺序组织的尽。ANSI将这种对象称为游标。理解当下同步是正确理解SQL的基本功。

坐这无异步不回回表(而是回到游标),使用了ORDER
BY子句的查询不能够因此作表表达式。表表达式包括:视图、内联表值函数、子查询、派生表和集体表达式。它的结果要回到给巴获取物理记录的客户端应用程序。例如,下面的派生表查询无效,并发出一个错误:

select * 
from(select orderid,customerid from orders order by orderid) 
as d

下的视图也会起错误:

create view my_view
as
select *
from orders
order by orderid

在SQL中,表表达式中未同意使用带有ORDER
BY子句的查询,而以T—SQL中倒闹一个差(应用TOP选项)。

     
所以要记住,不要也表中的行假设任何特定的依次。换句话说,除非你规定要发出序行,否则不要指定ORDER
BY 子句子。排序是得资本的。

# 执行HAVING过滤

HAVING子句主要及GROUP BY子句配合下,对分组得到的VT5虚拟表进行规范过滤。当自身执行测试语句被之HAVING count(b.order_id) < 2经常,将取得以下内容:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| baidu       | hangzhou |     NULL | NULL        |
| tx          | hangzhou |        6 | tx          |
+-------------+----------+----------+-------------+

立刻就是是虚构表VT6。

# SELECT列表

今日才见面执行到SELECT子句,不要看SELECT子句被勾勒于率先实施,就是第一只给实践之。

咱实行测试语句被之SELECT a.customer_id, COUNT(b.order_id) as total_orders,从虚拟表VT6挨甄选来我们要之情节。我们用取得以下内容:

+-------------+--------------+
| customer_id | total_orders |
+-------------+--------------+
| baidu       |            0 |
| tx          |            1 |
+-------------+--------------+

非,还没有终结,这单是杜撰表VT7。

SQL逻辑查询语句执行各个

尚记上面给起的那么同样抬高串的SQL逻辑查询规则也?那么,到底孰先实行,哪个后实施为?现在,我先行给出一个查询语句的实行顺序:

(7)     SELECT 
(8)     DISTINCT <select_list>
(1)     FROM <left_table>
(3)     <join_type> JOIN <right_table>
(2)     ON <join_condition>
(4)     WHERE <where_condition>
(5)     GROUP BY <group_by_list>
(6)     HAVING <having_condition>
(9)     ORDER BY <order_by_condition>
(10)    LIMIT <limit_number>

地方在各国条告词的前头都表明了履行顺序号,那么各修查询语句是怎样实行之为?

逻辑查询处理等简介

图片 2

  1. FROM:针对FROM子句被之面前片单说明执行笛卡尔积(Cartesian
    product)(交叉联接),生成虚拟表VT1
  2. ON:针对VT1应用ON筛选器。只有那些要<join_condition>为实在行才被插入VT2。
  3. OUTER(JOIN):苟指定了OUTER JOIN(相对于CROSS JOIN 或(INNER
    JOIN),保留表(preserved
    table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把个别只表都标记为保留表)中未找到匹配的且作为外部行添加到
    VT2,生成VT3.假设FROM子句包含两单以上之说明,则针对上一个连缀生成的结果说明及生一个表重复执行步骤1届步骤3,直到处理完毕所有的表为止。
  4. WHERE:对VT3应用WHERE筛选器。只有使<where_condition>为true的行才被插VT4.
  5. GROUP BY:依照GROUP BY子句被之列列表对VT4蒙的行分组,生成VT5.
  6. CUBE|ROLLUP:把超组(Suppergroups)插入VT5,生成VT6.
  7. HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为true的组才见面给插VT7.
  8. SELECT:处理SELECT列表,产生VT8.
  9. DISTINCT:将重的行从VT8饱受移除,产生VT9.
  10. ORDER BY:用VT9惨遭之行按ORDER BY
    子句被的列列表排序,生成游标(VC10).
  11. TOP:自从VC10的起来处于挑指定数量还是比重之推行,生成表VT11,并回调用者。

注:

笛卡尔积简单介绍:假设集合A={a, b},集合B={0, 1,
2},则少个集的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b,
2)}。

手续10,按ORDER
BY子句被的列列表排序上步返回的实践,返回游标VC10.即无异于步是首先步也是唯一一步可用SELECT列表中之列别名的步骤。这同一步不同让其它步骤的
是,它不返有效的申,而是回到一个游标。SQL是因集合理论的。集合不见面优先对她的行排序,它仅仅是成员的逻辑集合,成员的逐条无关紧要。对表进行清除序
的查询好回一个目标,包含本一定物理顺序组织的实行。ANSI把这种对象称为游标。理解这同样步是正确理解SQL的根基。

盖马上无异于步不回去回表(而是返回游标),使用了ORDER
BY子句的询问不克为此作表表达式。表表达式包括:视图、内联表值函数、子查询、派生表和公表达式。它的结果必须回到给想获取物理记录的客户端应用程序。例如,下面的派生表查询无效,并有一个荒唐:

select * 
from(select orderid,customerid from orders order by orderid) 
as d

脚的视图也会有错误:

create view my_view
as
select *
from orders
order by orderid

当SQL中,表表达式中莫允用含ORDER
BY子句的查询,而于T—SQL中倒是来一个两样(应用TOP选项)。

     
所以要牢记,不要吧表中的行假设任何特定的次第。换句话说,除非你规定要来序行,否则不要指定ORDER
BY 子句。排序是急需成本的。

     
每个步骤都见面发一个虚拟表,该虚拟表被用作下一个手续的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只是最后一步生成的表才会回到
给调用者。如果无于询问中指定某个平等子句,将跳了相应的手续。

未雨绸缪干活

率先声明下,一切测试操作都是当MySQL数据库及完,关于MySQL数据库的组成部分简单易行操作,请阅读一下章:

继承召开以下的早期准备工作:

1、新建一个测试数据库TestDB;

 create database TestDB;

2、创建测试表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;

3、插入测试数据;

 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)

4、准备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底客户。

执行LIMIT子句

LIMIT子句于高达等同步得到的VT8心虚拟表中选出从指定位置上马之指定行数据。对于无运用ORDER
BY的LIMIT子句,得到的结果同样是无序的,所以,很多时候,我们且见面视LIMIT子句会和ORDER
BY子句一起使用。

MySQL数据库的LIMIT支持如下形式之抉择:

LIMIT n, m

表示于第n长长的记下开始选m条记录。而多开发人员喜欢用该语句来解决分页问题。对于有些数目,使用LIMIT子句没有其它问题,当数据量非常很的当儿,使用LIMIT n, m大凡雅低效的。因为LIMIT的建制是历次都是从头开始扫描,如果要从第60万推行开始,读取3漫长数,就用先扫描定位及60万执行,然后重新展开读取,而扫描的长河是一个百般低效的过程。所以,对于充分数量处理时,是格外有必不可少当应用层建立一定的缓存机制(貌似现在之大数据处理,都发缓存哦)。

参照文档:

SQL逻辑查询语句执行各个

# 执行ON过滤

推行完笛卡尔积以后,接着便开展ON a.customer_id = b.customer_id法过滤,根据ON惨遭指定的口径,去丢那些无符合条件的数,得到VT2阐明,内容如下:

+-------------+----------+----------+-------------+
| customer_id | city     | order_id | customer_id |
+-------------+----------+----------+-------------+
| 163         | hangzhou |        1 | 163         |
| 163         | hangzhou |        2 | 163         |
| 9you        | shanghai |        3 | 9you        |
| 9you        | shanghai |        4 | 9you        |
| 9you        | shanghai |        5 | 9you        |
| tx          | hangzhou |        6 | tx          |
+-------------+----------+----------+-------------+

VT2纵是经ON原则筛选后得的发生因此数码,而连下去的操作以以VT2的根底及延续拓展。

# 执行DISTINCT子句

而在查询中指定了DISTINCT子句,则会创造同摆内存临时表(如果内存放不下,就得寄放于硬盘了)。这张临时表的说明结构和上同步产生的虚构表VT7凡是一律的,不同的凡针对性开展DISTINCT操作的排长了一个唯一索引,以这个来除还数据。

鉴于自家的测试SQL语句被并无用DISTINCT,所以,在该查询中,这无异于步不会见转变一个虚拟表。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图