top 1如何在sql server 2012中运行

时间:2017-06-22 17:13:24

标签: sql sql-server sql-server-2012

我有一张包含以下数据的表

  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

表的结果如下

enter image description here

select * from #t1 order by c3,c4

enter image description here

现在我运行以下查询,我得到了预期的结果

select  Cast(c4 AS VARCHAR(2)) + '~'+ Cast(c1 AS VARCHAR(100)) AS c5,* from #t1

以上查询的结果如下

enter image description here

现在我使用top 1来获取记录,我编写了如下代码

select top 1 Cast(c4 AS VARCHAR(2)) + '~'+ Cast(c1 AS VARCHAR(100)) AS c5,* from #t1

以上查询的结果如下

enter image description here

现在我使用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

enter image description here

问题:为什么最后2个查询的结果发生了变化,因为我希望得到相同的结果?

让我用这种方式问你:

当我在没有订单的情况下执行前1个查询时,我得到了93个记录值,所以当我按列顺序执行top 1时,我期望得到相同的结果。根据我的假设,在查询中,caluse没有对订单产生影响

提前致谢

编辑1

即使我执行了100次,结果也相同

编辑2

  • 服务器1

实际上我已经创建了一个主表并插入了上面的记录。在两个不同的会话中运行最后两个查询,结果是相同的

  • 服务器2

在第二台服务器上完成上述(服务器1中的相同步骤)。运行最后两个前1个查询,结果在两个会话中相同。

服务器和会话中的结果似乎相同。

结果

enter image description here

执行计划 enter image description here

2 个答案:

答案 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了解详情。