SQL Server SELECT最后N行

时间:2010-11-16 11:39:15

标签: sql sql-server performance sql-server-2008

这是一个众所周知的问题,但我发现的最佳解决方案是:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

我有一张有很多行的表格。使用该查询不是一种可能性,因为它需要大量时间。那么如何在不使用ORDER BY的情况下选择最后N行呢?

修改

抱歉重复this one

的问题

18 个答案:

答案 0 :(得分:80)

您可以使用此SQL使SQL服务器选择最后N行:

select * from tbl_name order by id desc limit N;

答案 1 :(得分:42)

我测试了JonVD的代码,但发现它非常慢,6s。

此代码为0。

SELECT TOP(5) ORDERID, CUSTOMERID, OrderDate    
FROM Orders where EmployeeID=5    
Order By OrderDate DESC

答案 2 :(得分:34)

您也可以使用ROW NUMBER BY PARTITION功能来完成此操作。可以找到一个很好的例子here

  

我正在使用Northwind数据库的Orders表...现在让我们检索员工5发出的最后5个订单:

SELECT ORDERID, CUSTOMERID, OrderDate
FROM
(
    SELECT ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY OrderDate DESC) AS OrderedDate,*
    FROM Orders
) as ordlist

WHERE ordlist.EmployeeID = 5
AND ordlist.OrderedDate <= 5

答案 3 :(得分:14)

如果要从表中选择最后一行数。

语法就像

 select * from table_name except select top 
 (numbers of rows - how many rows you want)* from table_name

这些陈述有效,但方式不同。谢谢你们。

 select * from Products except select top (77-10) * from Products

通过这种方式,您可以获得最后10行,但订单将显示为descnding方式

select top 10 * from products
 order by productId desc 

 select * from products
 where productid in (select top 10 productID from products)
 order by productID desc

 select * from products where productID not in 
 (select top((select COUNT(*) from products ) -10 )productID from products)

答案 4 :(得分:6)

“Id”被编入索引吗?如果没有,这是一件很重要的事情(我怀疑它已被编入索引)。

另外,您需要返回所有列吗?如果您实际上只需要较小的列子集,您可能能够获得速度的实质性改进,这些列可以由ID列上的索引完全满足 - 例如如果您在Id列上有一个NONCLUSTERED索引,而索引中没有包含其他字段,那么它必须对聚集索引进行查找才能实际返回其余列,这可能会构成很多查询的成本。如果它是一个CLUSTERED索引,或者包含你想在查询中返回的所有其他字段的NONCLUSTERED索引,那么你应该没问题。

答案 5 :(得分:6)

以非常通用的方式来支持SQL服务器

SELECT TOP(N) *
FROM tbl_name
ORDER BY tbl_id DESC

并且对于性能而言,它还不错(在服务器计算机上超过10,000条记录不到一秒钟)

答案 6 :(得分:5)

首先,你最多从

获得记录数
 Declare @TableRowsCount Int
 select @TableRowsCount= COUNT(*) from <Your_Table>

然后:

在SQL Server 2012中

SELECT *
FROM  <Your_Table> As L
ORDER BY L.<your Field>
OFFSET <@TableRowsCount-@N> ROWS
FETCH NEXT @N ROWS ONLY;

在SQL Server 2008中

SELECT *
FROM 
(
SELECT ROW_NUMBER() OVER(ORDER BY ID) AS sequencenumber, *
FROM  <Your_Table>
    Order By <your Field>
) AS TempTable
WHERE sequencenumber > @TableRowsCount-@N 

答案 7 :(得分:4)

select * from (select top 6 * from vwTable order by Hours desc) T order by Hours

答案 8 :(得分:4)

这是你可以在没有order by的情况下尝试的东西,但我认为它要求每一行都是唯一的。 N是您想要的行数,L是表格中的行数。

select * from tbl_name except select top L-N * from tbl_name

如前所述,返回的行是未定义的。

编辑:这实际上是狗慢。没有任何价值。

答案 9 :(得分:2)

此查询以正确的顺序返回最后N行,但性能很差

select *
from (
    select top N *
    from TableName t
    order by t.[Id] desc
) as temp
order by temp.[Id]

答案 10 :(得分:2)

在查询末尾使用带desby的desc来获取最后一个值。

答案 11 :(得分:2)

MS在t-sql中不支持LIMIT。大多数时候,我只会得到MAX(ID)然后减去。

select * from ORDERS where ID >(select MAX(ID)-10 from ORDERS)

当ID不连续时,它将返回少于10条记录。

答案 12 :(得分:1)

这可能不适合这个问题,但是......

OFFSET子句

OFFSET number子句使您可以跳过 number 行,然后返回行。

该文档链接是Postgres;我不知道这是否适用于Sybase / MS SQL Server。

答案 13 :(得分:0)

DECLARE @MYVAR  NVARCHAR(100)
DECLARE @step  int
SET @step = 0;


DECLARE MYTESTCURSOR CURSOR
DYNAMIC 
FOR
SELECT col FROM [dbo].[table]
OPEN MYTESTCURSOR
FETCH LAST FROM MYTESTCURSOR INTO @MYVAR
print @MYVAR;


WHILE @step < 10
BEGIN   
    FETCH PRIOR FROM MYTESTCURSOR INTO @MYVAR
        print @MYVAR;
        SET @step = @step + 1;
END   
CLOSE MYTESTCURSOR
DEALLOCATE MYTESTCURSOR

答案 14 :(得分:0)

我用来查询非常大的表 (超过1亿或1亿行) 中的 MOST RECENT 行的技术是限制的查询仅“读取”最近行的最近“N”百分比。这是真实世界的应用程序,例如我对非历史性近期天气数据或最近的新闻提要搜索或最近的GPS位置数据点数据执行此操作。

如果您确定您的行位于表格的最新前5%中,则这是巨大的性能提升。这样即使表上有索引,它也进一步将可能性限制在具有1亿或1亿行的表中仅5%的行。当旧数据需要物理磁盘读取而不仅逻辑内存读取时,情况尤其如此。

这比SELECT TOP |效率更高PERCENT | LIMIT,因为它不选择行,而只是限制要搜索的数据部分。

The child can be as large as it wants up to the specified size. 

答案 15 :(得分:0)

也许有点晚,但这是一个可以解决您问题的简单选择。

SELECT * FROM "TABLE" T ORDER BY "T.ID_TABLE" DESC LIMIT 5;

答案 16 :(得分:-1)

尝试使用EXCEPT语法 像这样:

   SELECT * 
    FROM   clientDetails 
    EXCEPT 
    (SELECT TOP (numbers of rows - how many rows you want) * 
     FROM   clientDetails) 

答案 17 :(得分:-1)

在不使用order by的情况下显示最后3行:

select * from Lms_Books_Details where Book_Code not in 
 (select top((select COUNT(*) from Lms_Books_Details ) -3 ) book_code from Lms_Books_Details)