一、select语句关键字的定义的顺序、执行顺序
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.新建一个测试数据库testDB
create datebase testDB
2.创建测试表table1和table2、
create table table1
(
customer_id verther (10) not null,
city verther (10) not null,
primary key (customer_id),
)enging=innoDB default charset=utf8;
create table table2
(
order_id int not null auto_increment,
customer_id verther (10) ,
primary key (order_id),
)enging=innoDB default charset=utf8
3.插入测试数据
insert into table1 (customer_id,city)values (a,shanghai)
insert into table2 (customer_id) values (a)
三、SQL逻辑查询测试语句
查询来自‘上海’且订单少于2的客户
select a.customer_id, count(b.order_id) as total_orders
from table as a
left join table2 as b
on a.customer_id=b.customer_id
where a.city='shanghai'
group by a.customer_id
having count(b.order_id)<2
order by total_orders DESC
四、执行顺序分析
在这些SQL语句执行的过程中,都会产生一个虚拟表,用来储存SQL语句的执行结果(这是重点),根据这个虚拟变化表,得到最终查询结果的过程,来分析整个SQL逻辑查询的执行顺序和过程。
1. 执行from语句
第一步执行from语句对两张表执行笛卡尔积,得到一张虚拟表。接下来在虚拟表上执行
2. 执行on过滤
执行from语句后,接着就执行on过滤,去掉不符合条件的数据得到表2,接下来在表2上来执行
3. 添加外部行
这一步只有在连接类型为 outer join 才会执行 ,例如:left outer join 、right outer join 、full outer join。大多数情况下会省略掉outer关键字,但outer表示外部行
添加外部行的工作就是在表2 的基础上添加保留表中被过滤条件过滤掉的数据,非保留表中的数据被赋予null值,最后生成虑拟表3,接下来在表3上执行
4. 执行where过滤
在表3上执行where过滤,只有符合<where_condition>的记录才会输出到虚拟表4
注意:1.由于数据还没有分组,还不能在where中对分组统计过滤
2.由于还没有进行列的选取操作,在select中也不能使用列的别名
5. 执行group by 分组
group by 主要对使用where子语句得到的虚拟表进行分组操作,得到虚拟表5
6. 执行having过滤
having 子句和group by 子句配合使用,对虚拟表5进行条件过滤,得到虚拟表6
7. 执行select列表
select写在第一句,但并不会先执行,执行select中的测试语句,进行筛选到我们想要的值得到表7
8. 执行distinct 子句
如果在查询中指定了distinct子句,则会创建一张内存临时表(如果内存放不下,则就会放在磁盘里)。这张临时表的表结构和产生的表7的表结构一样,不同的是对dintinct操作的列增加
了一个唯一索引,以此来去除重复数据
执行order by 语句
对虚拟表中的内容按照指定的列进行排序,然后返回一张新的虚拟表,就会储存在虚拟表8中
9. 执行limit 语句
limit子句从上述操作得到表8中选出从指定位置开始的指定行数据;对于没有应用order by的limit子句得到结果同样是无序的,所以通常情况下我们一般看到limit 和order by 一起使用。