top 1如何在sql server 2012中运行

Sma*_*003 5 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
Run Code Online (Sandbox Code Playgroud)

表的结果如下

在此输入图像描述

select * from #t1 order by c3,c4
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

select  Cast(c4 AS VARCHAR(2)) + '~'+ Cast(c1 AS VARCHAR(100)) AS c5,* from #t1
Run Code Online (Sandbox Code Playgroud)

上述查询的结果如下

在此输入图像描述

现在我使用前1来获取记录我已经编写了如下代码

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

上述查询的结果如下

在此输入图像描述

现在我使用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
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

让我用这种方式问你:

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

提前致谢

编辑1

即使我执行了100次,结果也一样

编辑2

  • 服务器1

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

  • 服务器2

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

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

结果

在此输入图像描述

执行计划在此输入图像描述

Joe*_*orn 9

如果您没有ORDER BY子句,则允许 Sql Server 以其想要的任何顺序显示结果.这意味着您可以获得与预期不同的结果.即使你有一个ORDER BY子句,如果结果集中的某些记录与同一个位置相关联,Sql Server也可以使用它想要的记录.

通常,当未指定订单时,Sql Server将以最快的顺序提供结果.这意味着随着时间的推移,结果将趋于有些一致,依赖于主键顺序或索引顺序之类的东西.在您的简单示例中,如果"基础"订单发生变化,那将会令人惊讶.

但重要的是要记住,这种排序完全没有保证.在实际生产环境中,如果您未指定订单,则结果可能会在执行之间发生变化.这可能会发生很多原因,但一个基本的例子是优化,其中两个查询可能在同一索引或表搜索上捎带,第二个查询在第一个查询的中间拾取搜索.另一个原因是表上的统计信息或行计数更改,以致Sql Server决定以不同于之前的方式使用(或不使用)索引.

因此,如果您真的关心在使用选择器时获取特定记录TOP,那么您也应该使用它ORDER BY,并确保您具体到足以明确无误.


对于此特定数据和查询示例,您有一个没有ORDER BY子句的示例和一个带有ORDER BY子句的示例,但第二个示例的子句仅按列c3和顺序排序c4.这些列对每条记录都具有相同的值.这意味着Sql Server仍可以免费使用最方便的订单,因为一切都很紧密.

但是,这并不意味着Sql Server将在第二个查询中使用与第一个查询中相同的顺序.添加该ORDER BY子句迫使Sql Server至少查看并评估结果集,然后才知道哪个记录属于哪个位置,并且该进程可以改变结果在内存中的排列,使得一个全新的顺序看起来最多方便.

因此,我们看看您是否关心结果,您不仅需要一个ORDER BY条款,而且该条款必须具有足够的选择性以保证您想要的顺序.如果要c1显示特定值,则应c1在您的ORDER BY子句中包含.


ssc*_*itz 0

如果没有正确的 order by 子句,您将继续得到意外的结果,因为表不一定以任何顺序读取。您在上一个查询中使用的 order by 语句强调了这个问题。由于所有数据都具有相同的 c3、c4 值,因此它们在返回时都具有相同的优先级。这意味着返回值的顺序未指定。我建议您查看这篇文章以了解更多信息。