正巧今天碰到一个sql的存储过程需要优化就顺便研究了下。Sql语句的执行顺序其实是如下的:
Select C.customerid, COUNT(O.orderid) AS numorders 7
FROM dbo.Customers AS C 1、
LEFT OUTER JOIN dbo.Orders AS O 2、
ON C.customerid = O.customerid 3、
WHERE C.city = ‘beijing’ 4、
GROUP BY C.customerid 5、
HAVING COUNT(O.orderid) < 3 6、
ORDER BY numorders 8
1、上面的语句其实是按我标的序号的顺序执行的,SELECT的执行顺序基本是最后的,而FROM则是第一步,并且是两个表先做外连接,然后通过ON滤掉不符合条件的结果。注意,如果是左链接或者是右连接会把不符合条件的记录根据连接的不同在重新添加到结果里,所以如果在ON这里做了某些WHERE时过滤的条件的话是不起作用的(例如:FROM TableA LEFT JOIN TableB ON TableA.DATE <> '1981-01-01'当做完LEFT连接后不符合条件的TableA表中的记录是会添加进来的,因为这里使用的是LFET JOIN),但是写到WHERE里的过滤条件是会最终过滤掉得,因为WHERE过滤时前面的JOIN操作已经完成,不会再影响结果集。
2、DISTINCT的特别之处在于他会把一些不必要的列过滤掉,如果在DISTINCT存在的情况下会把没有SELECT到的字段删除掉的,这时如果在使用ORDER BY那些不在SELECT中的字段就会出错了。
3、用过GROUP再用DISTINCT是无效的,因为GROUP已经把重复的列过滤掉了。
4、详细解释ON 和 WHERE 的区别
on后面是两个表连接的条件。连接的过程是两个表的记录先做内积,然后再根据ON的条件去除掉不符合条件的。例如on里面的条件可以这样写tableA.ID = tableB.ID AND tableB.ID = 2,这时两个表做完内积后会形成一个临时表,然后在这个临时表的基础上会把a表和b表id相等的记录并且tableB.id =2的ID去掉,这时,如果是内链接,则已经完成连接工作,但是如果是外连接,比如右连接,右边的表为tableB,这是如果右边表里面有某条记录被on的条件过滤掉了,就会自动再把这条记录补上,补上来的这条记录只有右表里的记录,左边表里的记录是空的。例如在做完内积有一条记录是