我有一张包含以下数据的表
IF OBJECT_ID('TEMPDB.DBO.#t1', 'U') IS NOT NULL
DROP TABLE #t1;
CREATE TABLE #t1
([c1] varchar(100), [c2] varchar(10), [c3] varchar(100), [c4] varchar(100))
;
INSERT INTO #t1
([c1], [c2], [c3], [c4])
VALUES
(93, '60-1.1.1.', 60, 3),
(104, '60-1.2.1.', 60, 3),
(102, '60-1.1.2.', 60, 3),
(101, '60-1.2.2.', 60, 3),
(92, '60-1.1.3.', 60, 3),
(96, '60-1.2.3.', 60, 3),
(103, '60-1.1.4.', 60, 3),
(94, '60-1.2.4.', 60, 3),
(105, '60-1.2.5.', 60, 3),
(97, '60-1.2.6.', 60, 3),
(99, '60-1.2.7.', 60, 3),
(100, '60-1.2.8.', 60, 3),
(98, '60-1.2.9.', 60, 3),
(95, '60-1.2.10.', 60, 3),
(91, '60-1.2.11.', 60, 3)
;
select * from #t1
表的结果如下
select * from #t1 order by c3,c4
现在我运行以下查询,我得到了预期的结果
select Cast(c4 AS VARCHAR(2)) + '~'+ Cast(c1 AS VARCHAR(100)) AS c5,* from #t1
以上查询的结果如下
现在我使用top 1来获取记录,我编写了如下代码
select top 1 Cast(c4 AS VARCHAR(2)) + '~'+ Cast(c1 AS VARCHAR(100)) AS c5,* from #t1
以上查询的结果如下
现在我使用top with order by子句然后我得到了以下结果
select top 1 Cast(c4 AS VARCHAR(2)) + '~'+ Cast(c1 AS VARCHAR(100)) AS c5,*
from #t1 order by c3,c4
问题:为什么最后2个查询的结果发生了变化,因为我希望得到相同的结果?
让我用这种方式问你:当我在没有订单的情况下执行前1个查询时,我得到了93个记录值,所以当我按列顺序执行top 1时,我期望得到相同的结果。根据我的假设,在查询中,caluse没有对订单产生影响
提前致谢
编辑1
即使我执行了100次,结果也相同
编辑2
实际上我已经创建了一个主表并插入了上面的记录。在两个不同的会话中运行最后两个查询,结果是相同的
在第二台服务器上完成上述(服务器1中的相同步骤)。运行最后两个前1个查询,结果在两个会话中相同。
服务器和会话中的结果似乎相同。
结果
答案 0 :(得分:9)
如果您没有ORDER BY
子句,Sql Server 允许以任何的顺序显示结果。这意味着您可以获得与预期不同的结果。即使你有一个ORDER BY
子句,如果结果集中的某些记录与同一个位置相关联,Sql Server也可以使用它想要的记录中的任何顺序。
通常,当未指定订单时,Sql Server将以最快的顺序提供结果。这意味着随着时间的推移,结果将趋于有些一致,依赖于主键顺序或索引顺序之类的东西。在您的简单示例中,如果“基础”订单发生变化,那将会令人惊讶。
重要的是要记住,这个排序完全没有保证。在实际生产环境中,如果您未指定订单,则结果可能会在执行之间发生变化。这可能会发生很多原因,但一个基本的例子是优化,其中两个查询可能在同一索引或表搜索上捎带,第二个查询在第一个查询的中间拾取搜索。另一个原因是表上的统计信息或rowcount更改,以致Sql Server决定以不同的方式使用(或不使用)索引。
因此,如果您真的关心在使用TOP
之类的选择器时获取特定记录,那么您也应该使用ORDER BY
,并确保您具体到明确无误。
对于此特定数据和查询示例,您有一个没有ORDER BY
子句的示例和一个带有ORDER BY
子句的示例,但第二个示例的子句仅按列{{1}排序}和c3
。 这些列对于每条记录都具有相同的值。这意味着Sql Server仍然可以自由地使用最方便的顺序,因为一切都是关联的。
但是,这并不意味着Sql Server将在第二个查询中使用与第一个查询中相同的顺序。添加c4
子句迫使Sql Server至少查看并评估结果集,然后才知道哪个记录属于哪个位置,并且该进程可以改变结果在内存中的排列,从而创建一个全新的订单似乎最方便。
因此,我们看到您是否关心结果,您不仅需要ORDER BY
子句,而且该子句必须具有足够的选择性以保证您想要的顺序。如果您希望显示特定的ORDER BY
值,则应在c1
子句中加入c1
。
答案 1 :(得分:0)
如果没有正确的order by子句,您将继续获得意外结果,因为表格不一定按任何顺序读取。您在上一个查询中使用的order by语句强调了此问题。由于所有数据都具有相同的c3,c4值,因此它们在返回时都具有相同的优先级。这意味着未指定返回值的顺序。我建议您查看this post了解详情。