繁体   English   中英

在SQL Server 2012中排名前1的工作方式

[英]how the top 1 works in 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

该表的结果如下

在此处输入图片说明

select * from #t1 order by c3,c4

在此处输入图片说明

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

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

以上查询的结果如下

在此处输入图片说明

现在我已使用前1个来获取记录,我已将代码编写如下

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

以上查询的结果如下

在此处输入图片说明

现在我将top和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个记录值,因此当我按列进行前1个查询时,我期望得到相同的结果。 在查询中,根据我的假设,没有因考量而影响订单

提前致谢

编辑1

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

编辑2

  • 服务器1

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

  • 服务器2

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

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

结果

在此处输入图片说明

执行计划 在此处输入图片说明

如果您没有ORDER BY子句,则允许 Sql Server 以其想要的任何顺序显示结果。 这意味着您可以获得与预期不同的结果。 即使您有一个ORDER BY子句,如果结果集中的某些记录在同一位置上绑定,则Sql Server可以对绑定的记录使用所需的任何顺序。

通常 ,如果未指定顺序,则Sql Server将以最快的顺序提供结果。 这意味着随着时间的流逝,结果将趋于一致,这取决于诸如主键顺序或索引顺序之类的事情。 在您的简单示例中,如果该“基本”顺序更改过,那将是令人惊讶的。

不过,请务必记住,这种顺序是不能保证的 在实际的生产环境中,如果不指定订单,结果在两次执行之间可能会发生变化。 发生这种情况的原因有很多,但一个基本的示例是一个优化,其中两个查询可能搭载在相同的索引或表查找上,而第二个查询则在第一个查询的中间进行。 另一个原因是表更改时的统计信息或行数使Sql Server决定使用(或不使用)索引的方式与以前不同。

因此,如果您真正在意使用TOP选择器时要获取特定记录,则也确实应该使用ORDER BY ,并确保您具有足够的明确性。


对于此特定的数据和查询样本,您有一个样本没有ORDER BY子句,而一个样本有ORDER BY子句,但是第二个样本子句仅按c3c4c4 这些列的每条记录都具有相同的值。 这意味着Sql Server仍然可以自由使用最方便的顺序,因为一切都可以。

但是,这并不意味着Sql Server将在第二个查询中使用与第一个查询相同的顺序。 添加ORDER BY子句强制Sql Server在知道哪个记录属于哪个位置之前,至少要查看并评估结果集,并且该过程可以改变结果在内存中的排列,从而使一个全新的顺序出现最方便。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM