为什么在SQL Server中没有`select last`或`select bottom`就像`select top`一样?

Raz*_*t4x 6 sql sql-server sql-server-2008 sql-server-2012

我知道这可能听起来像一个愚蠢的问题,但请耐心等待.在SQL-server中我们有

SELECT TOP N ...
Run Code Online (Sandbox Code Playgroud)

现在,我们可以按升序(默认情况下)获得前n行,很酷.如果我们想要在任何其他列上对记录进行排序,我们只需在order by子句中指定,就像这样......

SELECT TOP N ... ORDER BY [ColumnName]
Run Code Online (Sandbox Code Playgroud)

更酷.但如果我想要这一last行怎么办?我只是写这样的东西......

SELECT TOP N ... ORDER BY [ColumnName] DESC
Run Code Online (Sandbox Code Playgroud)

但对此有一点关注.我说关心而不是问题因为它实际上不是问题.通过这种方式,我可以根据该列获取最后一行,但如果我想要插入的最后一行该怎么办.我知道SCOPE_IDENTITY,IDENT_CURRENT@@IDENTITY,但考虑heap(表中没有clustered index)没有任何标识列,并从许多地方多次访问(不要进入这个太多,因为这些多操作的方式和时间正在发生,这并未"关注主要的事情).所以在这种情况下,似乎没有一种简单的方法可以找到最后插入的行.有些人可能会这样回答

如果从[table]中选择*,则sql结果窗口中显示的最后一行将是最后一行插入的.

对于任何想到这一点的事情,事实并非如此,至少并非总是如此,你可以永远依赖(msdn,请阅读本Advanced Scanning).

所以问题归结为这一点,就像标题本身一样.为什么SQL Server没有

SELECT LAST
Run Code Online (Sandbox Code Playgroud)

或者说

SELECT BOTTOM
Run Code Online (Sandbox Code Playgroud)

或类似的东西,我们不必指定Order By,然后它会在执行查询时给表中插入最后一条记录(同样我不会详细说明如果未提交的话会导致这种结果如何读或幻读().

但是,如果仍然有人争辩说,如果不谈论这些阅读水平,我们就不能谈论这个问题,那么,对于他们来说,我们可以使它的行为与TOP工作方式相同,但恰恰相反.但如果你的论点是,那么我们就不会像往常那样需要它

SELECT TOP N ... ORDER BY [ColumnName] DESC
Run Code Online (Sandbox Code Playgroud)

那我真的不知道该说些什么.我知道我们可以做到这一点,但是有没有任何基于关系的原因,或某些基于语义的原因,或者由于我们没有不能有这个原因的其他原因SELECT LAST/BOTTOM.我不是在寻找方法Order By,我正在寻找原因,为什么没有它或不能拥有它.

额外的 ,我不知道很多有关NOSQL是如何工作的,但我工作(只是一点点)与mongodbelastic search,还有太多不似乎是这样的事.他们没有这个原因的原因是因为之前没有人曾经拥有它,还是因为某种原因不合理?

UPDATE

并不需要知道,我需要通过降或不指定顺序.在回答或评论之前,请先阅读问题并理解我的疑虑.我知道如何获得最后一排.这甚至不是问题,主要问题归结为为什么不select last/bottom喜欢它的对应物.

更新2

从答案后,弗拉基米尔彼得,我只是想更新我知道,如果我做的顺序是不能保证SELECT TOP没有ORDER BY.我知道我之前在问题中所写的内容可能会让人产生一种印象,我不知道情况如何,但如果你只是向下看,我已经给了一个msdn的链接,并提到了SELECT TOP没有ORDER BY不保证任何订购.所以请不要在你的答案中加上我的陈述错误,因为我已经在几行(我提供了链接msdn)之后澄清了自己.

Vla*_*nov 14

你可以这样想.

SELECT TOP N没有ORDER BY返回一些 N行,既不是第一个,也不是最后一个,只是一些.它未返回哪些行.您可以运行相同的语句10次,每次获得10组不同的行.

所以,如果服务器有一个语法SELECT LAST N,那么这个语句的结果ORDER BY将不再是未定义的,这正是你现有的SELECT TOP N没有ORDER BY.


你在问题中强调,你知道并理解我在下面写的内容,但我仍然会保留它,以便让所有人都能在以后阅读.

你在问题中的第一个短语

在SQL-server SELECT TOP N ...中,我们现在可以按升序(默认情况下)获得前n行,很酷.

是不正确的.随着SELECT TOP N没有ORDER BY你得到N"随机"行.好吧,不是真的随机,服务器不会故意从一行到另一行随机跳转.它选择了一些确定性的方法来扫描表格,但是可以有许多不同的方法来扫描表格,服务器可以随时根据需要更改所选择的路径.这就是"未定义"的含义.

服务器不跟踪哪些行被插入到表中的顺序,那么你再次假设的结果SELECT TOP N,而不ORDER BY被其行被插入表中的顺序决定是不正确的.


那么,你最后一个问题的答案

为什么不select last/bottom喜欢它的对手.

是:

  • 没有ORDER BY结果SELECT LAST N将与SELECT TOP N- undefined的结果完全相同.
  • ORDER BY结果与结果SELECT LAST N ... ORDER BY X ASC完全相同SELECT TOP N ... ORDER BY X DESC.

因此,没有必要有两个关键词做同样的事情.


彼得的回答有一个很好的观点:这个词TOP有点误导.它实际上意味着LIMIT结果设置为某些行.

顺便说一句,自SQL Server 2012以来,他们增加了对ANSI标准的支持OFFSET:

OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
[
  FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
]
Run Code Online (Sandbox Code Playgroud)

在这里添加另一个关键词是合理的,它是ANSI标准并且它增加了重要的功能 - 分页,以前不存在.


我要感谢@ Razort4x在这里提供了一个非常好的MSDN链接."高级扫描"部分有一个很好的称为"旋转木马扫描"机制的例子,它说明了为什么SELECT没有ORDER BY子句就无法保证从语句返回的结果的顺序.

这个概念经常被误解,我在这里看到了很多关于SO的问题,如果他们从该链接中引用它将会大大受益.


你的问题的答案

为什么SQL Server没有SELECT LAST或者说SELECT BOTTOM类似的东西,我们不必指定它ORDER BY,然后它会在执行查询时最后一条记录插入表中(同样我不会进入有关如何在未提交的读取或幻像读取的情况下导致此结果的详细信息).

是:

魔鬼在你想要省略的细节中.要知道哪条记录是"在执行查询时最后插入表中"(并以某种一致/非随机方式知道),服务器需要以某种方式跟踪此信息.即使在多个同时运行的事务的所有场景中都是可能的,但从性能的角度来看,它很可能是昂贵的.不是每个人SELECT都会请求这些信息(事实上很少或根本没有),但跟踪这些信息的开销总是存在.

因此,您可以这样想:默认情况下,服务器不会执行任何特定的操作来了解/跟踪插入行的顺序,因为它会影响性能,但如果您需要知道可以使用例如,IDENTITY列.微软可能已经设计了服务器引擎,它IDENTITY在每个表中都需要一个列,但是它们使它成为可选的,这在我看来是好的.我比服务器更了解哪些表需要IDENTITY列,哪些不需要.

摘要

我想总结一下,你可以SELECT LAST不用ORDER BY两种不同的方式看待.

1)当你期望SELECT LAST表现符合现有的SELECT TOP.在这种情况下,结果是未定义两个LASTTOP,即结果是实际上是相同的.在这种情况下,它归结为(不)有另一个关键字.语言开发人员(在这种情况下是T-SQL语言)总是不愿意添加关键字,除非有充分的理由.在这种情况下,它显然是可以避免的.

2)当你期望SELECT LAST表现为SELECT LAST INSERTED ROW.顺便说一句,这应该扩展相同的期望,SELECT TOP以表现为SELECT FIRST INSERTED ROW或添加新的关键字LAST_INSERTED,FIRST_INSERTED以保持现有的关键字TOP完整.在这种情况下,它归结为性能并增加了此类行为的开销.目前,如果您不需要此信息,服务器允许您避免此性能损失.如果您确实需要它,IDENTITY如果您仔细使用它是一个非常好的解决方案.