SQL Server SELECIONAR ÚLTIMAS N Linhas

139

Esta é uma pergunta conhecida, mas a melhor solução que encontrei é algo como:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

Eu tenho uma mesa com muitas linhas. Não é possível usar essa consulta porque leva muito tempo. Então, como posso fazer para selecionar as últimas N linhas sem usar ORDER BY?

EDITAR

Desculpe pergunta duplicada deste

Diego
fonte
O que se entende por "último N"? Sem uma ordem, "último N" não faz muito sentido. Se você quer dizer "último N a ser inserido", não pode confiar no SQL Server para fornecer isso a você - você deve usar uma cláusula ORDER BY.
precisa
@Daniel Renshaw: O último N da tabela sem forçar o SQL Server a ordenar todas as tabelas porque fica muito lento
Diego
A consulta na sua pergunta é a melhor maneira. Se idestiver indexado, ele apenas fará a varredura desse índice em sentido inverso e parará após as primeiras 5 linhas. Se não estiver indexado, será necessário fazer uma TOP Nclassificação. Isso não será pior do que qualquer outra maneira de fazê-lo. Ele não classificar a tabela inteira (embora seria necessário examinar a tabela inteira)
Martin Smith

Respostas:

38

Você pode fazer isso usando o recurso ROW NUMBER BY PARTITION. Um ótimo exemplo pode ser encontrado aqui :

Estou usando a tabela Pedidos do banco de dados Northwind ... Agora, vamos recuperar os últimos 5 pedidos feitos pelo Funcionário 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
JonVD
fonte
1
Recurso PARTITION ROW número por usa uma espécie bem .. você precisa para classificar a tabela de números de linha de atribuição para cada registro ...
Sadhir
Isso é verdade, mas sem uma espécie de natureza, isso simplesmente não funcionará, a melhor solução é indexar as principais colunas que estão sendo atingidas e executadas com algo como a consulta acima.
JonVD
101

Você pode fazer com que o SQL server selecione as últimas N linhas usando este SQL:

select * from tbl_name order by id desc limit N;
Niru Mukund Shah
fonte
2
E quanto à compatibilidade de versões?
Fractaliste
63
Isso não funciona no SQL Server. Parece um recurso MySQL, PostgreSQL e SQLite.
Tim Friesen 14/10
3
Todos os produtos enumerados são definitivamente servidores SQL. Se você quiser falar sobre o servidor MS SQL, por que não nomear isso?
gena2x
4
Estou confuso, a pergunta pergunta como criar uma consulta de seleção "sem usar ORDER BY" e a consulta de seleção na sua resposta tem "ordem de". Isso é algum tipo de "ordem por" sem "ordem por"?
Robert Sinclair
5
@ gena2x esta pergunta está identificada como SQL Server. Essa tag refere-se ao Microsoft SQL Server.
Martin Smith
51

Testei o código do JonVD, mas achei muito lento, 6s.

Este código levou 0s.

SELECT TOP(5) ORDERID, CUSTOMERID, OrderDate    
FROM Orders where EmployeeID=5    
Order By OrderDate DESC
ABI
fonte
4
Quantas linhas ?? Quando você tem muitas linhas que podem ser MUITO lentas #
Diego Diego
@ Diego Por que é isso? Se você foi OrderDateindexado, deve ser essencialmente igualmente rápido escolher a primeira ou a última N linha de uma consulta. Sei que há uma chance de OrderDatecorrelacionar bem com a ordem inserida, mas esse é um efeito colateral, na melhor das hipóteses, e ainda requer uma varredura de tabela, não? (E eu não acho que isso responde ao que os pontos op para como um joguete melhor formulada de sua pergunta : isto é, sem ordenação)
ruffin
1
@ Diego - Por que você acha que isso será mais lento do que a resposta que você aceitou?
Martin Smith
2
Isso retorna as linhas de cabeça para baixo. É necessário reordenar por eles para recuperar o pedido original.
Mark
15

Se você deseja selecionar o último número de linhas de uma tabela.

Sintaxe será como

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

Essas declarações funcionam de maneiras diferentes. obrigado pessoal

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

Desta forma, você pode obter as últimas 10 linhas, mas a ordem mostrará o modo decrescente

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)
Prafulla Sutradhar
fonte
7

De uma maneira muito geral e para oferecer suporte ao SQL Server, aqui está

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

e para o desempenho, não é ruim (menos de um segundo para mais de 10.000 registros na máquina do servidor)

Hakan Fıstık
fonte
1
10.000 registros não são nada para se preocupar com desempenho. Quando você começa a falar de milhões de registros do que você pode começar a pensar sobre o desempenho
Dom84
6

O "ID" está indexado? Caso contrário, isso é uma coisa importante a se fazer (suspeito que já esteja indexado).

Além disso, você precisa retornar TODAS as colunas? Você poderá obter uma melhoria substancial na velocidade se, na verdade, precisar apenas de um subconjunto menor de colunas que possa ser INTEGRALMENTE atendido pelo índice na coluna ID - por exemplo, se você tiver um índice NÃO EXCLUSIVO na coluna Id, sem outra campos incluídos no índice, seria necessário fazer uma pesquisa no índice clusterizado para que o restante das colunas retornasse e isso poderia estar compensando muito o custo da consulta. Se é um índice CLUSTERED ou NONCLUSTERED que inclui todos os outros campos que você deseja retornar na consulta, então você deve estar bem.

AdaTheDev
fonte
6

Primeiro, você obtém a contagem de registros mais

 Declare @TableRowsCount Int
 select @TableRowsCount= COUNT(*) from <Your_Table>

E depois :

No SQL Server 2012

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

No 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 
Ardalan Shahgholi
fonte
4

Aqui está algo que você pode tentar sem um, order bymas acho que exige que cada linha seja única. Né o número de linhas que você deseja, Lé o número de linhas na tabela.

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

Como observado anteriormente, quais linhas são retornadas são indefinidas.

EDIT: este é realmente cachorro lento. De nenhum valor realmente.

Dzamo Norton
fonte
4
select * from (select top 6 * from vwTable order by Hours desc) T order by Hours
quinto
fonte
2

Essa consulta retorna as últimas N linhas na ordem correta, mas seu desempenho é ruim

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

use desc com orderby no final da consulta para obter os últimos valores.

Sara
fonte
1

Isso pode não ser o ajuste certo para a pergunta, mas…

Cláusula OFFSET

A OFFSET numbercláusula permite que você pule um número linhas e depois retorne as linhas.

Esse link de documento é para o Postgres; Não sei se isso se aplica ao Sybase / MS SQL Server.

Basil Bourque
fonte
1
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
Slava
fonte
1

O MS não suporta LIMIT no t-sql. Na maioria das vezes, eu apenas recebo MAX (ID) e subtraio.

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

Isso retornará menos de 10 registros quando o ID não for seqüencial.

olafk
fonte
0

Uma técnica usada para consultar as linhas MAIS RECENTES em tabelas muito grandes (mais de 100 milhões ou mais de 1 bilhão de linhas) está limitando a consulta a "ler" apenas a porcentagem "N" mais recente de LINHAS RECENTES. São aplicativos do mundo real, por exemplo, faço isso para Dados Meteorológicos Recentes não históricos, ou pesquisas recentes de feeds de Notícias ou dados recentes de pontos de dados de localização GPS.

Essa é uma grande melhoria de desempenho se você tiver certeza de que suas linhas estão entre os TOP 5% mais recentes da tabela, por exemplo. De modo que, mesmo que existam índices nas Tabelas, ele limita ainda mais as possibilidades a apenas 5% das linhas em tabelas que possuem mais de 100 milhões ou mais de 1 bilhão de linhas. Esse é especialmente o caso quando Dados Antigos exigirão leituras de Disco Físico e não apenas Memória Lógica leituras da .

Isso é bem mais eficiente que o SELECT TOP | PERCENT | LIMIT, pois não seleciona as linhas, mas limita apenas a parte dos dados a serem pesquisados.

DECLARE @RowIdTableA BIGINT
DECLARE @RowIdTableB BIGINT
DECLARE @TopPercent FLOAT

-- Given that there is an Sequential Identity Column
-- Limit query to only rows in the most recent TOP 5% of rows
SET @TopPercent = .05
SELECT @RowIdTableA = (MAX(TableAId) - (MAX(TableAId) * @TopPercent)) FROM TableA
SELECT @RowIdTableB = (MAX(TableBId) - (MAX(TableBId) * @TopPercent)) FROM TableB

SELECT *
FROM TableA a
INNER JOIN TableB b ON a.KeyId = b.KeyId
WHERE a.Id > @RowIdTableA AND b.Id > @RowIdTableB AND
      a.SomeOtherCriteria = 'Whatever'
CodeCowboyOrg
fonte
-1

Para exibir as últimas 3 linhas sem usar order by:

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) 
abhinay
fonte
1
Isso não fornecerá resultados previsíveis. De acordo com os documentos do MSDN do Sql Server ( msdn.microsoft.com/en-us/library/ms189463.aspx ): "Quando o TOP é usado em conjunto com a cláusula ORDER BY, o conjunto de resultados é limitado ao primeiro N número de pedidos linhas; caso contrário, ele retornará o primeiro número N de linhas em uma ordem indefinida. "
caveman_dick
-1

Tente usar a EXCEPTsintaxe.
Algo assim:

   SELECT * 
    FROM   clientDetails 
    EXCEPT 
    (SELECT TOP (numbers of rows - how many rows you want) * 
     FROM   clientDetails) 
mayur godhani
fonte
Mesma resposta que @Prafulla Sutradhar
DMK
-1

Talvez um pouco tarde, mas aqui está uma seleção simples que resolve sua pergunta.

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