1、sql编程有许多独特之处,如:面向集合的思维方式、查询元素的逻辑处理顺序、三值逻辑。如果不掌握这些知识就开始用sql编程,得到的将是冗余的、性能低下的代码,而且难以维护。
2、在sqlserver中负责生成实际工作计划(执行计划)的组件是:查询优化器(query optimizer)。只有在确保结果集正确的前提下,优化器才会走捷径。明确区分查询的逻辑处理和物理处理是非常重要的。
3、逻辑查询的各个阶段:
(5) select (5-2) distinct (5-3) top () (5-1) (1) from (1-j) join on |(1-a) apply as |(1-p) pivot () as |(1-u) unpivot () as (2) where (3) group by (4) having (6) order by ;
第一步:from :表示出查询的来源表,在联结运算中涉及的阶段是(1-j1)笛卡儿积、(1-j2)on筛选器和(1-j3)添加外部行。并生成虚拟表vt1。
1.1、笛卡儿积:两表执行笛卡儿积,生成虚拟表vt1-j1。
1.2、on筛选器:针对vt1-j1中满足on为true的行,插入vt1-j2。
1.3、添加外部行:如果指定了outer join (相对于cross join或inner join ),则将保留表中没有匹配的行,作为外部行添加,生成vt1-j3。
第二步:where:根据where 子句中的谓词对vt1中的数据进行行筛选,只对结果为true的行,插入vt2。
第三步:group by :根据group by中的列表,将vt2进行分组,每一组只有一个结果行,生成vt3。
第四步:having:根据having出现的谓词对vt3金信筛选,只让结果为true的组才插入vt4。
第五步:select:处理select 子句中的元素,产生vt5。
5.1、计算表达式:根据select 列表中的表达式,生成vt5-1。
5.2、distinct:删除vt5-1中重复的行,生成vt5-2。
5.3、top:根据order by 子句定义逻辑排序,从vt5-2中选择前面指定数量或百分比的行,生产vt5-3。
第六步:order by :根据order by 子句中指定的列名,对vt5-3进行排序。生成游标vc6。
对于三值逻辑:
a、所有的查询筛选器(on、where 和having )都把null当作false来处理。
b、check约束中的null值被当作true来对待。
c、unique约束、集合运算(union 和except)、及排序和分组操作,认为两个null是相等的。
注意:
1、如果from 子句中有多个表运算符,则按从左到右的顺序进行处理。每个表运算符的结果作为下一个表运算符的左输入,最后生成虚拟表作为下一阶段的输入。
2、因为在where之前还没对数据分组,所以where 子句不能使用聚合。在筛选器中,on对保留表中部分行的删除并不是最终的,而where是最终的。只有使用外联结的时候,on和where才有逻辑区别。
3、如果在查询中指定了group by ,后续所有步骤都只能在指定的分组上操作。
4、having是唯一可用于分组数据的筛选器。
5、由于sql具有多个运算同时计算(all-at-once operation),所以select 语句中的逻辑顺序是无关的。
6、order by 是唯一可以使用select 中别名的步骤。
