SQL的查询模型

逻辑查询处理的各个阶段
一个普通格式的查询
(5)SELECT DISTINCT TOP N <SELECTLIST>
(1)FROM <LEFTTB> JOIN <RIGHTTB> ON <ONPRE>
(2)WHERE <WHEREPRE>
(3)GROUP BY <SPECIFICATION>
(4)HAVING <HAVINGPRE>
(6)ORDER BY <ORDERBYLIST>
SQL与其他的编程语言不同,SQL第一个处理的子句是FROM子句,上面已标记出一个Select语句的执行顺序,ORDER BY是最后执行,SELECT是第五步执行。
具体看看Select的顺序执行:
(1)FROM:
标识出查询的来源表,处理表运算符,每一个表运算符也会有一系列子阶段:笛卡尔积、on筛选器、添加外部行。from最后会生成一张虚拟表。笛卡尔积是对两张表执行交叉联接。on筛选器是根据on子句中的谓词进行筛选,取值为true时保留。添加外部行是如果Join是outer join,则将保留表中被删除的行需要重新添加回去。
(2)WHERE:
根据where子句中出现的谓词对查询表进行筛选,谓词为true的记录会保留。
(3)GROUP BY:
对GROUP BY子句中的列名进行分组,每一个分组最后只有一行数据。
(4)HAVING:
根据HAVING子句的谓词对上一步返回的表进行筛选,为true的保留。
(5)SELECT:
SELECT子句中会有子阶段:SELECT列表表达式、DISTINCT 、TOP 。
(6)ORDER BY:
根据ORDER BY子句的列表进行排序,生成游标。


在搞清执行顺序之后,我们对每一步的内部执行进行探索:
步骤1;FROM阶段
from阶段负责标识表或要查询的表,如果指定了表运算符,这个阶段要按从左到右顺序对这些运算符进行处理。
这里主要是cross join交叉联接,inner join内联接,outer join外联接,其中外联接还被分成left outer join 、right outer join 、full outer join。
其中cross join是交叉联接,是笛卡尔积,返会一个n*m的表。
inner join是在cross join 返回结果的基础上根据on筛选器中的谓词进行筛选,为true保留。
outer join外联连是在内联接的返回结果基础上,将保留表中被删除的行添加回来,添加回来的数据叫做外部行,外部行中非保留表的属性被赋值为Null。
小讨论:三值逻辑
SQL中的重要特性,在SQL里面的谓词可能取值:true、false和unknown。unknown通常出现在涉及Null值的逻辑表达式中。true的取反是false,unknown取反还是unknown。
在查询筛选器中(on、WHERE、HAVING)把unknown看做false。
check约束中的unknown看做true。
在Unique约束、集合运算符(union),以及排序、分组,认为两个Null值是相等的。
步骤2:WHERE阶段
对上一步返回的虚拟表中的所有行应用where筛选器,逻辑为true的保留,因为在where阶段之前还没有进行分组操作,所以在where子句中不能使用聚合函数。对于包含outer join子句时,on筛选器和where筛选器的区别是on在添加外部行之前,where在这之后,on筛选器的结果不是最终的,有可能在添加外部行时被重新添加回来,where筛选器是最终的结果。
步骤3:GROUP BY阶段
在GROUP BY阶段,根据指定的列表将上一步返回的表进行分组。这里指定的列表称为分组集,分组是按照分组集中所有属性值的每一个唯一组合标识出一个组。表中的每一行数据都和一个组关联,且紧关联到一个组。最终为每一组生成一行数据,则后面所有的步骤(SELECT 、HAVING)只能指定在每一组上得到标量(单个)值的表达式。在这个阶段两个Null被认为是相等的。
步骤4:HAVING 阶段
having筛选器用于对上一步返回的表中的组进行筛选,逻辑为true保留,having是唯一可用于分组数据的筛选器。
步骤5:select阶段
select子句出现在查询语句的最前面,但是放在第五步处理,将构造最终返回给调用者的表,其中有三个子阶段:计算表达式 可以对列名取别名、distinct、Top选项。
步骤6:ORDER BY阶段
这一步按ORDER BY子句中的列名列表对上一步返回的表进行排序,返回游标。ORDER BY是唯一可以使用select列表中创建列别名的步骤。

ORDER BY与top同时使用情况:
在逻辑上,top选项是在ORDER BY排序阶段之前,作为select的一部分处理,它的目的是基于某种顺序的逻辑定义,筛选出请求的数量或者百分比的行。
可惜top没有自己排序子句,而是借助同一查询中的ORDER BY子句来提供逻辑排序,但是ORDER BY子句又是用于对查询结果的排序。这样一来就不能为top和查询结果分别定义排序逻辑,这就是top选项的限制。所以sql Server是这样实现两者关系的:当最外层查询中使用top,ORDER BY 有两种作用:为top定义行的逻辑优先顺序、为结果游标定义排序顺序。当top定义表表达式时,只有第一种作用,会返回一个表。

其他的一些小知识
表运算符:join等
集合运算符:union等
over子句与聚合函数一起使用:
select OrdreID,Count(*) over(partition by customerid) as num from orders

select customerid,ROW_NUMBER() over(partition by customerid ORDER BY OrdreID DESCas num from orders


over子句与row_number函数一起使用:
SELECT
    ROW_NUMBER() OVER (ORDER BY A.InDate ASC) AS RowNumber
    ,A.[SysNo]
    ,A.[Content]
    ,A.[Type]
    ,A.[InDate]
FROM INFO A WITH(NOLOCK)

原文地址:https://www.cnblogs.com/lmfeng/p/2444257.html