所以 on、where、having 这三个都可以加条件的子句中,on 是最先执行,where 次之,having 最后。有时候如果这先后顺序不影响中间结果的话,那最终结果是相同的。但因为 on 是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的。
根据上面的分析,可以知道 where 也应该比 having 快点的,因为它过滤数据后才进行 sum,所以 having 是最慢的。但也不是说 having 没用,因为有时在步骤3还没出来都不知道那个记录才符合要求时,就要用 having 了。
在两个表联接时才用 on 的,所以在一个表的时候,就剩下 where 跟 having 比较了。在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是 where 可以使用 rushmore 技术,而 having 就不能,在速度上后者要慢。
如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程, where 的作用时间是在计算之前就完成的,而 having 就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。
在多表联接查询时,on 比 where 更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由 where 进行过滤,然后再计算,计算完后再由 having 进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里。
--------------------------------------------------------------------------------
第三节 四种链接的区别及用法 链接:
作为动词,它表示将两个或多个表的内容结合在一起并产生一个结果集,该结果集对每个表的列和行进行合并。表的联接一般都使用它们共有的数据。例如,您可以对有一个共同 pub_id 列的 titles 表和 publishers 表联接,产生一个包含书名信息和出版商信息的结果集。
作为名词,表示对表进行联接的过程或结果,如在术语\内部联接\中表示对表联接的一种特殊的方法。
联接条件(join condition)
一个比较子句,它指定了表是如何通过它们的联接字段相联系的。最普通的联接条件是相等(一个等联接),在等联接中联接字段的值必须相同。例如,您可以通过在 titles 表和 publishers 表的 pub_id 列中查找相匹配的值联接这两个表。然而,任何比较运算符都可以是比较条件的一部分。
内部联接(inner join)
一个联接,在该联接中只有当联接字段的值满足某些特定的准则时才将两个表的记录进行结合并添加到一个查询结果中。例如,在查询设计器视图中,表之间的缺省联接是一个内部联接,它只有当联接字段的值相等时才从两个表中选择记录。
外部联接(outer join)
一个联接,该联接还包括那些和联接表中记录不相关的记录。您可以创建一个外部联接的三种变形来指定所包括的不匹配行:左外部联接、右外部联接和完全外部联接。
左外部联接(left outer join)
一种外部联接类型,在该联接中包括第一个命名表(左边的表,它出现在 JOIN 子句的最左边)的所有行。右边表中没有匹配的行不出现。例如,您可以在 titles 表和 publishers 表之间创建一个左外部联接,以包括所有的书名,不论书名有无出版商的信息。
右外部联接(right outer join)
一种外部联接,在该联接中包括第二个命名表(右边的表,出现在 JOIN 子句中的最右边)的所有行。不包括左边表中没有匹配的行。例如,titles 表和 publishers 表之间的一个右外部联接将包括所有的出版商,甚至包括那些在 titles 表中没有书名的出版商。
以上是MSDN中对链接的定义。现在我们就从这四种链接所使用的不同方法来看他们的结果有什么不同。 titles 表
sh(书号) ph(出版商编号) 232342 001 0432 003 82478123 005
publishers 表
ph(出版商编号) mc(出版商名称) 001 红虎 002 rmh 003 hazl
现要把这两个表的内容合成如下的表结构:
sh(书号) ph(出版商编号) mc(出版商名称)
现在看看采用四种链接方法的结果会有什么不同。先说说他们的命令: 内联接:
sele titles.sh,publishers.ph,publishers.mc ;
from titles inner join publishers ; &&内联接中的inner是可以省略的 on titles.ph=publishers.ph 外联接:
sele titles.sh,publishers.ph,publishers.mc ; from titles outer join publishers ; on titles.ph=publishers.ph 左联接:
sele titles.sh,publishers.ph,publishers.mc ; from titles left join publishers ; on titles.ph=publishers.ph 右联接:
sele titles.sh,publishers.ph,publishers.mc ; from titles right join publishers ; on titles.ph=publishers.ph
大家可能看到,除了在join之前的那个关键字不同之外,其他地方是一模一样的,链接条件(即 on 那一部
分)也是一样的。结果: 内链接:
232342 001 红虎 0432 003 hazl 全链接:
232342 001 001 红虎 Null Null 002 rmh 0432 003 003 hazl 82478123 005 Null Null 左链接:
232342 001 001 红虎 0432 003 003 hazl 82478123 005 Null Null 右链接:
232342 001 001 红虎 Null Null 002 rmh 0432 003 003 hazl 所以我们很容易记住:
1、左链接:就是以join的左边那个表为\主\,以 titles.ph=publishers.ph 为判断标准,不管右边的表有没有对应的记录,都要把左边表的记录放在结果中去,但右边表没有相应的记录那应该放个什么数值进去?答案是就放个 Null,表示没有。在左链接中,某记录在右边表,却不在左边表,那是不放进去结果去的,原因是左边表才是\主\,要不要放由它决定:它有的,就一定放进去,它没有的,就不要了。
2、右链接:和左链接一样,只不过为\主\的一方调过来了,换成是由右边做\主\。
3、内链接:和左、右链接不同,它一定要左、右两边都有的记录才会放进结果,如果有某个记录不存在于
任何一边,那这个记录是不会出现在结果中去的。
4、外链接:跟内联接相,反,相当于左、右链接的合并:不管什么情况,只要某个记录出现在这两个表,就一定会出现在结果中去,然后象左、右链接的处理方法一样,用Null来填充没有对应值的字段。
注:以上说的\有\、\没有\,意思是以 titles.ph=publishers.ph 为判断标准来下决定的。比如当前 titles 表的ph是 \,而在 publishers 中,没有一个记录的 ph 的值是 \的,所以就说 \这个值在 titles 有,在 publisher 中没有,这样 titles.ph 为 \的记录就会被选中,最后放在结果中去。
大家如果想一下,这个 on 的作用跟 where、having 似乎有点类似,都是起到过滤的作用:根据条件选取所取的记录,而根据命令的工作流程,这个 on 是比 where、having 都要早执行的,而它里面的条件表达式又不一定是 titles.ph=publishers.ph 的形式,还可以继续扩充,变成一个很复杂的条件表达式,从而完成一个很有效的、where 和 having 都不能实现的过滤功能。具体的比较请看 on、where、having的区别 一节。
刚才举的例子,表中的 ph 都是没有重复的。现在以内联接为例,举个判断字段中内容有重复的例子:
Temp1 temp2 Aa aa 1 1 1 2 2 2 3 2
sele temp1.aa,temp2.aa ; from temp1 join temp2 ; on temp1.aa=temp2.aa 运行结果是: 1 1 1 1 2 2 2 2