IREDPUREmysql执行查询语句的11个步骤(分享1)ZERO2016/02/19每个人都会犯错误,有的人把犯过的错误记录下来,进一步总结,形成了自己的一套理论;有的人,则在同一个错误上一错再错,不停的抱怨,然后再犯错,然后再抱怨,产生了一个死循环……1、项目结束后的思考每个项目的结束,每个人都会有自己的收获,不同水平的人总结出来的东西可能不一样!但是对自己而言,都是进步,都是让自己在原有的基础上强大了一点点。
我们在每个项目结束后,都应该对自己做一个总结,这是我们强大的来源,日记月累,必定是一笔不小的财富!2、mysql查询语句执行的11个步骤(8) select(9) distinct <fields name>(1) from(1) <left table>(3) <join type> join (1) <right table>(2) on <join condition>(4) where <where condition>(5) group by <group by field>(6) with {cube | rollup}(7) having <having condition>(10) order by <order by fields>(11) limit <limit_number>以上是这个11个步骤,这是《mysql技术内幕之sql编程》这本书上面得出的结论,有兴趣的同学也可以去看下,很不错的一本书!ps: Paul DuBois( 杜波依斯) Sun 公司MySQL文档团队的技术作者、开源社区和MySQL社区活跃的技术专家,同时也是一名数据库管理员。
他曾参与过MySQL在线文档的编写工作接下来我们举一个例子,分别解释sql语句的执行流程!3、举例说明sql语句的执行流程【1】进行准备工作CREATE TABLE `Customer` (`CustomerID` varchar(10) NOT NULL,`CityName` varchar(10) NOT NULL,PRIMARY KEY (`CustomerID`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;LOCK TABLES `Customer` WRITE;INSERT INTO `Customer` VALUES ('163','hangzhou'),('9you','shanghai'),('tx','hangzhou'), ('baidu','hangzhou');UNLOCK TABLES;================================================================================================================= CREATE TABLE `Orders` (`OrdersID` int(11) NOT NULL AUTO_INCREMENT,`CustomerID` varchar(10) DEFAULT NULL,PRIMARY KEY (`OrdersID`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;LOCK TABLES `Orders` WRITE;INSERT INTO `Orders` VALUES (1,'163'),(2,'163'),(3,'9you'),(4,'9you'),(5,'9you'),(6,'tx'),(7,null);UNLOCK TABLES;=====================================================================================================最终结果如下:通过如下语句查询来杭州,且订单小于2的用户,并且查询出来他们的订单数量,查询的结果按照订单数从大到小排列:select Customer.CustomerID, Customer.CityName, count(Orders.CustomerID) as OrdersNumberfrom Customer left join Orderson Customer.CustomerID = Orders.CustomerIDwhere Customer.CityName='HangZhou'group by Customer.CustomerIDhaving count(Orders.CustomerID) < 2order by OrdersNumber desc;ps:在得出正确的语句之前,我写了两次错误的sql,个人认为还是很有借鉴意义的:select Customer.CustomerID, Customer.CityName, count(*) as OrdersNumberfrom Customer inner join Orderson Customer.CustomerID = Orders.CustomerID where Customer.CityName='HangZhou'group by Customer.CustomerID having count(*) < 2 order by OrdersNumber desc;select Customer.CustomerID, Customer.CityName, count(*) as OrdersNumberfrom Customer left join Orderson Customer.CustomerID = Orders.CustomerID where Customer.CityName='HangZhou'group by Customer.CustomerID having count(*) < 2从结果上看是错误的,但是,为什么错误,请各位自行脑补!【2】得到联表的笛卡尔积也就是执行sql语句中的第一步骤,得到笛卡尔积。
在数学中,两个集合X和Y的笛卡儿积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员。
假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
执行下面的语句得到笛卡尔积,形成了虚拟表V1:ps:每次上个步骤产生的虚拟表,作为下一步骤的输入【3】执行on语句进行过滤也就是语句中的Customer.CustomerID = Orders.Customer,在sql语句中的有三个条件会进行过滤,on是其中之一,此外还有where、having语句进行过滤!执行如下语句,我们可以模拟笛卡尔积(虚拟表V1)过滤后的数据,得到虚拟表V2ps:什么是三值逻辑表达式?在php中,逻辑表达式只有两种返回结果,true和false。
但是在mysql中,却会返回三个值,true、false、unknow<phpvar_dump(null === null);//返回结果是true?>只有返回结果是1该记才会被保留【4】根据连接类型,确定保留表,添加保留数据执行这个步骤,只有在连接为outer join的请款下才会发生,如果不是的话,将自行跳过这个步骤!这里,我们有必要,对联表类型解释一下!联表分为Outer Join 和 Inner Join,两种类型!Outer Join分为:(1)left outer join,左外连接,以左表作为保留表 (2)right outer join ,右外连接,以右表作为保留表 (3)full outer join,全外连接,左右都是保留表!inner join:inner join一种。
ps:select * from Customer inner join Orders on Customer.CustomerID = Orders.CustomerID; 等于 select * from Customer, Orders where Customer.CustomerID = Orders.CustomerID;执行如下语句,向虚拟表V2中添加保留表的数据,剩余字段使用null进行填充,得到虚拟表V3:ps:如果要联表超过两个或者以上,执行步骤又是什么呢?基于虚拟表V3,同第三个表连接,形成新的笛卡尔积,执行On条件过滤,根据连接类型确定保留表,如此循环,得到虚拟表,作为下一步的输入【5】执行where过滤基于虚拟表V3,执行where条件的过滤,得到虚拟表V4执行如下语句,可以模拟得到:【6】执行group 进行分组基于虚拟表V4,执行group进行分组,得到虚拟表V5,由于分组之后只会展示第一条数据,所以下面的sql仅仅是位得到虚拟表V5罢了【7】执行rollup这里并没有执行rollup,所以跳过这个步骤ps:个人认为没什么卵用。
知道有这回事就可以了(1)当你使用 ROLLUP时, 你不能同时使用 ORDER BY子句进行结果排序。
换言之, ROLLUP 和ORDER BY 是互相排斥的。
然而,你仍可以对排序进行一些控制。
在MySQL中, GROUP BY 可以对结果进行排序,而且你可以在GROUP BY列表指定的列中使用明确的 ASC和DESC关键词,从而对个别列进行排序。
(不论如何排序被ROLLUP添加的较高级别的总计行仍出现在它们被计算出的行后面)(2)LIMIT可用来限制返回客户端的行数。
LIMIT 用在 ROLLUP后面, 因此这个限制 会取消被ROLLUP添加的行【8】执行having,对分组进行过滤,产生虚拟表V6基于虚拟表V5,执行having过滤,得到虚拟表V6,下面的sql仅仅是位得到虚拟表V6【9】执行select语句选中输出列基于虚拟表V6,执行select语句,得到虚拟表V7【10】执行distinct语句,进行去重基于虚拟表V7,执行distinct有,去掉重复的数据,这里没有执行该步骤,自动跳过【11】执行order by语句,进行排序基于虚拟表V7,执行order by,进行排序,得到虚拟表V8【12】执行limit语句,从指定位置开始获取指定的行数!这里并没有执行该步骤,自动跳过参考文献:《mysql技术内幕》。