2011-04-04 50 views
1

Sql Server 2008行为异常。当我执行存储过程时,输出的顺序与我直接为相同参数执行语句的顺序不同。我不确定我做错了什么。请帮忙!!!当直接执行语句和从存储过程执行语句时会有不同的输出?

这是一个简单的查询结构并解释它的作用。

Top 10 Query1 
Union all 
Top 10 Query2 
Order by name 

a。当你在proc中运行它时: 从查询1获取前10,然后从查询2获取前10,最后它执行命令

b。当您打开查询时: 从查询1开始应用订单,然后取得前10名,并从查询2开始应用订单,然后取得前10名。这很奇怪,它用同样的方法做了2件不同的事情查询。

Output from Procedure 
Name           Cost Price 
A2 Bag Stickerss DO NOT STOCKTAKES    24 
aaaaaa           5 
aaaaaa           7.5 


Output from Query 
Name           Cost Price 
A2 Bag Stickerss DO NOT STOCKTAKES    24 
A2 Bag Stickerss DO NOT STOCKTAKES    27 
aaaaaa           5 
aaaaaa           7.5 
aaaaaa           9 
+3

你在你的存储过程,你的即席查询有一个ORDER'条款BY'?如果没有任何'ORDER BY',**没有**担保订单 - 你可以得到任何东西 – 2011-04-04 15:38:23

+0

Hi Marc_s,这两段代码都有order by子句。 – 2011-04-04 15:40:50

+0

一个相同的ORDER BY?那么你应该得到相同的结果....(除了那些没有排序的列)。你可以**向我们展示**查询吗? – 2011-04-04 15:41:54

回答

3

TOP没有ORDER BY是不确定的。

它只是意味着“选择任何10条记录”。因此,您正在从查询1中选择任意一组10个结果,并从查询2中选择任意一组10个记录,然后按名称对这20个记录进行排序。

其中TOP 10取决于您选择的计划(这可能在存储过程中会有所不同)您需要为每个查询添加一个按顺序(对一组没有关系的列)以使其生成确定性。

您当前的查询是像

SELECT TOP 10 * 
FROM master..spt_values 
UNION ALL 
SELECT TOP 10 * 
FROM master..spt_values 
ORDER BY name 

Plan 1

你看到的SQL Server只是增加了一个TOP迭代计划的两个分支,以限制两个查询的输出,那么这些送入联盟然后按名称排序。 SQL Server为此选择了聚簇索引扫描,因此结果可能会是聚簇索引顺序type,number,name中的前10位(尽管这不应该依赖于这两者,如果没有指定的顺序,则指示TOP引用的是任何集的10行将是有效的,因为它在这里使用advanced scanning功能是完全有效的,并且给你一个任意的10行,它知道它在高速缓存中,因为它们刚刚被其他查询的扫描所读取。)

要重写为每个元素指定的TOP...ORDER BY,您可以使用CTE如下。

;WITH Query1 AS 
(
SELECT TOP 10 * 
FROM master..spt_values 
ORDER BY name,number,type 
), Query2 AS 
(
SELECT TOP 10 * 
FROM master..spt_values 
ORDER BY number,type,name 
) 

SELECT * 
FROM Query1 
UNION ALL 
SELECT * 
FROM Query2 
ORDER BY name 

Plan 2