Answers:
SELECT
columns
FROM
(
SELECT TOP 200
columns
FROM
My_Table
ORDER BY
a_column DESC
) SQ
ORDER BY
a_column ASC
没必要。您可以使用,ORDER BY
而只需更改排序DESC
即可获得相同的效果。
抱歉,我认为我没有看到正确的答案。
该TOP
X功能显示在未确定的订单记录。根据该定义,BOTTOM
无法定义函数。
独立于任何索引或排序顺序。当您执行an时,您将ORDER BY y DESC
首先获得y值最高的行。如果这是一个自动生成的ID,则应显示其他记录中建议的最后添加到表中的记录。然而:
TOP
功能进行比较,则会对性能产生重大影响正确的答案应该是不存在,也不能等同TOP
于获取最下面的行。
从逻辑上讲
BOTTOM (x) is all the records except TOP (n - x), where n is the count; x <= n
例如,从员工中选择前1000名:
在T-SQL中
DECLARE
@bottom int,
@count int
SET @bottom = 1000
SET @count = (select COUNT(*) from Employee)
select * from Employee emp where emp.EmployeeID not in
(
SELECT TOP (@count-@bottom) Employee.EmployeeID FROM Employee
)
在解决方案中实现ORDER BY子句的任何答案似乎都没有抓住重点,或者实际上不了解TOP会给您带来什么。
TOP返回无序查询结果集,该结果集将记录集限制为返回的前N条记录。(从Oracle的角度看,这类似于在ROWNUM <(N + 1)处添加。
任何使用订单的解决方案都可能返回由TOP子句返回的行(因为数据集首先是无序的),具体取决于订单使用的条件
TOP的用处是,一旦数据集达到一定大小N,它将停止获取行。您无需获取所有数据即可了解数据的外观。
为了准确地实现BOTTOM,将需要无序获取整个数据集,然后将数据集限制为最终的N条记录。如果您要处理大表,那将不会特别有效。也不会必然给你什么,你认为你所要求的。数据集的末尾不一定是“最后插入的行”(对于大多数DML密集型应用程序可能不是)。
同样,不幸的是,实现ORDER BY的解决方案在处理大型数据集时可能会造成灾难性的后果。如果我有100亿条记录并想要最后10条记录,那么订购100亿条记录并选择最后10条记录是非常愚蠢的。
这里的问题是,当与TOP进行比较时,BOTTOM没有我们想到的含义。
一次又一次地插入,删除,插入,删除记录时,存储中将出现一些间隙,以后,如果可能,将插入行。但是,当我们选择TOP时,我们经常看到的似乎是已排序的数据,因为它可能早已插入到表的存在中。如果该表没有很多删除,则它似乎是有序的。(例如,创建日期可能早于表创建本身的时间)。但是实际情况是,如果这是一个大量删除的表,则前N行可能根本不像这样。
所以-这里的底线(双关语意味是)是要BOTTOM N记录的人实际上并不知道他们要的是什么。或者,至少,他们要的是什么以及BOTTOM的实际含义是不同的。
因此-解决方案可能满足请求者的实际业务需求...但是不满足成为BOTTOM的标准。
insert
声明,将行放入一个没有索引的大表中。(在开始为表编制索引之前,我先填充了该表。)由于重新启动或其他原因,我失去了客户端会话,现在我想看看是否有新添加的行。如果表的“底部”行是我最近的行之一,则我知道操作已完成。如果“底部”行是其他内容,那么不能保证,我必须扫描整个表以确保...但是我很可能可以通过快速检查“底部”来节省一些时间,就像您在“最佳'。
正如“保护者一”所指出的那样,“贾斯汀·埃斯蒂尔”当前接受的答案不是正确的答案。
据我所知,到目前为止,没有其他答案或评论提供与作者所要求的BOTTOM(x)相当的东西。
首先,让我们考虑一个需要此功能的场景:
SELECT * FROM Split('apple,orange,banana,apple,lime',',')
这将返回一个包含一列和五个记录的表:
如您所见:我们没有ID列;我们不能按返回的列排序;而且我们无法像使用前两个记录那样使用标准SQL选择后两个记录。
这是我尝试提供的解决方案:
SELECT * INTO #mytemptable FROM Split('apple,orange,banana,apple,lime',',')
ALTER TABLE #mytemptable ADD tempID INT IDENTITY
SELECT TOP 2 * FROM #mytemptable ORDER BY tempID DESC
DROP TABLE #mytemptable
这里是一个更完整的解决方案:
SELECT * INTO #mytemptable FROM Split('apple,orange,banana,apple,lime',',')
ALTER TABLE #mytemptable ADD tempID INT IDENTITY
DELETE FROM #mytemptable WHERE tempID <= ((SELECT COUNT(*) FROM #mytemptable) - 2)
ALTER TABLE #mytemptable DROP COLUMN tempID
SELECT * FROM #mytemptable
DROP TABLE #mytemptable
我决不是声称在所有情况下都可以使用此方法,但可以提供预期的结果。
您需要做的就是扭转您的状况ORDER BY
。添加或删除DESC
它。
用另一种方式排序的问题是,它常常不能很好地利用索引。如果您需要选择许多不在开头或结尾的行,它也不是很可扩展。另一种方法如下。
DECLARE @NumberOfRows int;
SET @NumberOfRows = (SELECT COUNT(*) FROM TheTable);
SELECT col1, col2,...
FROM (
SELECT col1, col2,..., ROW_NUMBER() OVER (ORDER BY col1) AS intRow
FROM TheTable
) AS T
WHERE intRow > @NumberOfRows - 20;
试试这个。
declare @floor int --this is the offset from the bottom, the number of results to exclude
declare @resultLimit int --the number of results actually retrieved for use
declare @total int --just adds them up, the total number of results fetched initially
--following is for gathering top 60 results total, then getting rid of top 50. We only keep the last 10
set @floor = 50
set @resultLimit = 10
set @total = @floor + @resultLimit
declare @tmp0 table(
--table body
)
declare @tmp1 table(
--table body
)
--this line will drop the wanted results from whatever table we're selecting from
insert into @tmp0
select Top @total --what to select (the where, from, etc)
--using floor, insert the part we don't want into the second tmp table
insert into @tmp1
select top @floor * from @tmp0
--using select except, exclude top x results from the query
select * from @tmp0
except
select * from @tmp1
SELECT TOP 10*from TABLE1 ORDER BY ID DESC
其中ID是TABLE1的主键。
首先,使用表的原始顺序在子查询中创建索引:
ROW_NUMBER () OVER (ORDER BY (SELECT NULL) ) AS RowIndex
然后,按照RowIndex
您在主查询中创建的列的顺序对表进行排序:
ORDER BY RowIndex DESC
最后使用TOP
所需的行数:
SELECT TOP 1 * --(or 2, or 5, or 34)
FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL) ) AS RowIndex, *
FROM MyTable) AS SubQuery
ORDER BY RowIndex DESC