T-SQL中的子查询,一步步详细说明
时间:2011-01-29 来源:浪雪
假设你需要Orders表,并且想返回每一条order的信息,并且包括前一条order的ID。但是你知道在表中的行记录是没有顺序的,这时我们需要把概念转换成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;
注意:在“引用外面字段的子查询”的笔记中,可以知道子查询
(SELECT MAX(O2.orderid)
FROM Sales.Orders AS O2 WHERE O2.orderid < 01.orderid)
返回的是一个标量值,但是这里奇怪的就是,为什么标量值还用MAX?????
因为用了MAX所以返回的才是一个标量值,前后逻辑顺序我弄错了。还有那篇笔记里用的是等于运算符,
而我这里是小于运算符,返回的结果当然不一样,这里返回的是一个结果集。
01.orderid是从最大的数字开始(比如说是10248),所以
应该不是从最大,而是按照表中记录的固有顺序。表中的orderid = 10248恰好是第一条而已。
这里很容易理解,比如说小于10250的结果集是10248和10249,选择最大的当然是10249了。
剩下的依次类推。
注意,这张表主要主要注意的是prevorderid这一列,而不是orderid列的顺序。顺序是表中原有
的顺序,和这里的查询语句无关。
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
3.外部查询有了第一行记录。
4.自引用产生了遍历效果,因此再度进入到子查询里,这时子查询变为
(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.外部查询有了第三条记录
接下来的依次类推
相关阅读 更多 +