SQL Server SELECCIONE LAS ÚLTIMAS N filas

139

Esta es una pregunta conocida, pero la mejor solución que he encontrado es algo como:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

Tengo una mesa con muchas filas. No es posible utilizar esa consulta porque lleva mucho tiempo. Entonces, ¿cómo puedo hacer para seleccionar las últimas N filas sin usar ORDER BY?

EDITAR

Lo siento pregunta duplicada de este

Diego
fuente
¿Qué se entiende por "última N"? Sin una orden, "última N" no tiene mucho sentido. Si quiere decir "la última N en ser insertada", entonces no puede confiar en que SQL Server le dará eso; debe usar una cláusula ORDER BY.
Daniel Renshaw el
@Daniel Renshaw: El último N de la tabla sin obligar a SQL Server a ordenar toda la tabla porque se vuelve muy lento
Diego
La consulta en su pregunta es la mejor manera. Si idestá indexado, simplemente escaneará ese índice en reversa y se detendrá después de las primeras 5 filas. Si no está indexado, tendrá que hacer una TOP Nordenación. Esto no será peor que cualquier otra forma de hacerlo. No clasifica toda la tabla (aunque necesitaría escanear toda la tabla)
Martin Smith

Respuestas:

38

Puede hacerlo utilizando la función NÚMERO DE FILA POR PARTICIÓN también. Un gran ejemplo se puede encontrar aquí :

Estoy usando la tabla de pedidos de la base de datos Northwind ... Ahora recuperemos los últimos 5 pedidos realizados por el empleado 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
fuente
1
PARTICIÓN función FILA POR NÚMERO utiliza una especie, así .. que necesita para ordenar la tabla para asignar números de fila para cada registro ...
Sadhir
Esto es cierto, pero sin una especie de naturaleza, esto simplemente no funcionará, la mejor solución es indexar las principales columnas que se están ejecutando y ejecutar con algo como la consulta anterior.
JonVD
101

Puede hacer que el servidor SQL seleccione las últimas N filas con este SQL:

select * from tbl_name order by id desc limit N;
Niru Mukund Shah
fuente
2
¿Qué hay de la compatibilidad de versiones?
Fractaliste
63
Esto no funciona en SQL Server. Parece una característica de MySQL, PostgreSQL y SQLite.
Tim Friesen
3
Todos los productos enumerados son definitivamente servidores SQL. Si quieres hablar sobre el servidor MS SQL, ¿por qué no nombrarlo así?
gena2x
44
Estoy confundido, la pregunta pregunta cómo crear una consulta de selección "sin usar ORDER BY" y la consulta de selección en su respuesta tiene "ordenar por". ¿Es esto una especie de "ordenar por" sin "ordenar por"?
Robert Sinclair
55
@ gena2x esta pregunta está etiquetada como SQL Server. Esa etiqueta se refiere a Microsoft SQL Server.
Martin Smith
51

Probé el código de JonVD, pero descubrí que era muy lento, 6 segundos.

Este código tomó 0s.

SELECT TOP(5) ORDERID, CUSTOMERID, OrderDate    
FROM Orders where EmployeeID=5    
Order By OrderDate DESC
ABI
fuente
44
¿Cuántas filas? Cuando tienes muchas filas que pueden ser MUY lentas
Diego
@ Diego ¿Por qué es eso? Si se ha OrderDateindexado, debería ser esencialmente igual de rápido elegir la primera o la última N filas de una consulta. Me doy cuenta de que existe una posibilidad que se OrderDatecorrelaciona bien con el orden insertado, pero ese es un efecto secundario en el mejor de los casos, y aún requiere un escaneo de tabla, ¿no? (Y no creo que responda a lo que el OP señala como una mejor frase redactada de su pregunta : es decir, sin clasificar)
ruffin
1
@Diego - ¿Por qué crees que esto será más lento que la respuesta que aceptaste?
Martin Smith
2
Esto devuelve las filas al revés. Luego debe volver a ordenar por ellos para recuperar el pedido original.
Mark
15

Si desea seleccionar los últimos números de filas de una tabla.

La sintaxis será como

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

Estas declaraciones funcionan pero de diferentes maneras. gracias chicos.

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

de esta manera puede obtener las últimas 10 filas, pero el orden mostrará una forma descendente

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
fuente
7

De una manera muy general y para soportar el servidor SQL aquí está

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

y para el rendimiento, no es malo (menos de un segundo para más de 10,000 registros en la máquina del servidor)

Hakan Fıstık
fuente
1
bueno, 10,000 registros no es nada en lo que debas preocuparte por el rendimiento. Cuando comienzas a hablar de millones de registros, puedes comenzar a pensar en el rendimiento
Dom84
6

¿Está "Id" indexado? Si no, eso es algo importante (sospecho que ya está indexado).

Además, ¿necesita devolver TODAS las columnas? Es posible que pueda obtener una mejora sustancial en la velocidad si solo necesita un subconjunto de columnas más pequeño que pueda ser TOTALMENTE atendido por el índice en la columna ID, por ejemplo, si tiene un índice NO CLUSIFICADO en la columna Id, sin otro los campos incluidos en el índice, entonces tendría que hacer una búsqueda en el índice agrupado para que el resto de las columnas regresen y eso podría ser una gran parte del costo de la consulta. Si se trata de un índice CLUStered, o un índice NO CLUStered que incluye todos los demás campos que desea devolver en la consulta, entonces debería estar bien.

AdaTheDev
fuente
6

Primero obtienes un recuento récord de

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

Y entonces :

En SQL Server 2012

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

En 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
fuente
4

Aquí hay algo que puede probar sin un order bypero creo que requiere que cada fila sea única. Nes el número de filas que desea, Les el número de filas en la tabla.

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

Como se señaló anteriormente, las filas que se devuelven no están definidas.

EDITAR: esto es realmente perro lento. Sin valor realmente.

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

Esta consulta devuelve las últimas N filas en el orden correcto, pero su rendimiento es deficiente

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

use desc con orderby al final de la consulta para obtener los últimos valores.

Sara
fuente
1

Puede que esto no se ajuste a la pregunta, pero ...

Cláusula OFFSET

La OFFSET numbercláusula le permite saltar varias filas y luego devolver filas después de eso.

Ese enlace de documento es a Postgres; No sé si esto se aplica a Sybase / MS SQL Server.

Albahaca Bourque
fuente
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
fuente
1

MS no admite LIMIT en t-sql. La mayoría de las veces solo obtengo MAX (ID) y luego resta.

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

Esto devolverá menos de 10 registros cuando la ID no sea secuencial.

olafk
fuente
0

Una técnica que uso para consultar las filas MÁS RECIENTES en tablas muy grandes (más de 100 millones o más de 1 000 millones de filas) está limitando la consulta a "leer" solo el porcentaje "N" más reciente de FILAS RECIENTES. Se trata de aplicaciones del mundo real, por ejemplo, hago esto para datos meteorológicos recientes no históricos, o búsquedas recientes de noticias o datos de puntos de datos de ubicación GPS recientes.

Esta es una gran mejora en el rendimiento si sabe con certeza que sus filas están en el TOP 5% más reciente de la tabla, por ejemplo. De tal manera que incluso si hay índices en las Tablas, limita aún más las posibilidades a solo el 5% de las filas en las tablas que tienen más de 100 millones o 1+ billones de filas. Este es especialmente el caso cuando los datos antiguos requerirán lecturas de disco físico y no solo lógica en memoria lecturas de .

Esto es mucho más eficiente que SELECT TOP | POR CIENTO | LIMIT ya que no selecciona las filas, sino que simplemente limita la parte de los datos a buscar.

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
fuente
-1

Para mostrar las últimas 3 filas sin 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
fuente
1
Esto no proporcionará resultados predecibles. De acuerdo con los documentos MSDN del Servidor SQL ( msdn.microsoft.com/en-us/library/ms189463.aspx ): "Cuando TOP se usa junto con la cláusula ORDER BY, el conjunto de resultados se limita al primer N número de pedidos filas; de lo contrario, devuelve el primer número N de filas en un orden indefinido ".
caveman_dick
-1

Intenta usar la EXCEPTsintaxis.
Algo como esto:

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

Tal vez un poco tarde, pero aquí hay una selección simple que resuelve su pregunta.

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