假设你需要Orders表,并且想返回每一条order的信息,并且包括前一条order的ID(在本例中就是orderid, orderdate, empid, custid,prevorderid),。但是你知道在表中的行记录是没有顺序的,这时我们需要把概念转换成SQL的等价思想:最大的值小于当前的值

用SQL语句表示如下
 
SELECT orderid, orderdate, empid, custid,
(SELECT MAX(O2.orderid)
FROM Sales.Orders AS O2
WHERE O2.orderid < O1.orderid) AS prevorderid
FROM Sales.Orders AS O1;
在我第一看到O2.orderid < O1.orderid这种形式的比较的时候,我最想明白的就是O1.orderid的取值是什么?
其实,连接外部的子查询就相当于
for(){
  for(){
  }
}
也就是说,Order表中的每一行都和Order表整张表进行比较,这个是通过别名来实现的。 
因此我们很容易理解,01.orderid的取值是按照表中记录的原本顺序的第一条记录。因此表中的O1.orderid = 10248。
接着的MAX(O2.orderid),比如说小于10250的结果集是10248和10249,选择最大的当然是10249了。
这个是查询结果
orderid     orderdate                   empid       custid      prevorderid
----------- --------------------------- ----------- ----------- -----------
10248 2006-07-04 00:00:00.000 5 85 NULL
10249 2006-07-05 00:00:00.000 6 79 10248
10250 2006-07-08 00:00:00.000 4 34 10249
10251 2006-07-08 00:00:00.000 3 84 10250
10252 2006-07-09 00:00:00.000 4 76 10251
...
11073 2008-05-05 00:00:00.000 2 58 11072
11074 2008-05-06 00:00:00.000 7 73 11073
11075 2008-05-06 00:00:00.000 8 68 11074
11076 2008-05-06 00:00:00.000 4 9 11075
11077 2008-05-06 00:00:00.000 1 65 11076

(830 row(s) affected)
 
 

单独看上面的说明,我想初学者可能还是不明白,因此最后我再完整的阐述下整个运行过程
SELECT orderid, orderdate, empid, custid,
(SELECT MAX(O2.orderid)
FROM Sales.Orders AS O2
WHERE O2.orderid < O1.orderid) AS prevorderid
FROM Sales.Orders AS O1;



1.给Sales.Orders设置别名O1
2.O1.orderid 转换成 Sales.Orders表的第一条记录(10248)。
所以这时应该是
(SELECT MAX(O2.orderid)
FROM Sales.Orders AS O2
WHERE O2.orderid < 10248
)
接着返回查询的结果集null,因为不存在比10248还小的orderid
3.外部查询有了第一行记录。
4.自引用产生了遍历效果 Select产生了遍历效果,因此再度进入到子查询里,这时子查询变为
(SELECT MAX(O2.orderid)
FROM Sales.Orders AS O2
WHERE O2.orderid < 10249
)
返回查询结果集为10248,MAX后仍然是10248。
5.外部查询有了第二行记录
6.继续进入到子查询
(SELECT MAX(O2.orderid)
FROM Sales.Orders AS O2
WHERE O2.orderid < 10250
)
返回的查询结果集为10249和10248,MAX后返回的是10249
7.外部查询有了第三条记录
接下来的依次类推
posted on 2011-01-29 18:34  一路转圈的雪人  阅读(538)  评论(0编辑  收藏  举报