SQL Server SELECT LAST N Zeilen

139

Dies ist eine bekannte Frage, aber die beste Lösung, die ich gefunden habe, ist etwa:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

Ich habe eine Tabelle mit vielen Zeilen. Es ist nicht möglich, diese Abfrage zu verwenden, da dies viel Zeit in Anspruch nimmt. Wie kann ich also die letzten N Zeilen auswählen, ohne ORDER BY zu verwenden?

BEARBEITEN

Entschuldigung, doppelte Frage von diesem

Diego
quelle
Was ist mit "letztes N" gemeint? Ohne eine Bestellung macht "last N" nicht viel Sinn. Wenn Sie "das letzte N, das eingefügt werden soll" meinen, können Sie sich nicht darauf verlassen, dass SQL Server Ihnen dies gibt - Sie müssen eine ORDER BY-Klausel verwenden.
Daniel Renshaw
@ Daniel Renshaw: Das letzte N der Tabelle, ohne SQL Server zu zwingen, alle Tabellen zu bestellen, weil es sehr langsam wird
Diego
Die Abfrage in Ihrer Frage ist der beste Weg. Wenn idindiziert, wird dieser Index nur umgekehrt gescannt und nach den ersten 5 Zeilen angehalten. Wenn es nicht indiziert ist, muss eine TOP NSortierung durchgeführt werden. Dies wird nicht schlimmer sein als jede andere Art, es zu tun. Es sortiert nicht die gesamte Tabelle (obwohl es die gesamte Tabelle scannen müsste)
Martin Smith

Antworten:

38

Sie können dies auch mit der Funktion ROW NUMBER BY PARTITION tun. Ein gutes Beispiel finden Sie hier :

Ich verwende die Tabelle "Bestellungen" der Northwind-Datenbank ... Lassen Sie uns nun die letzten 5 Bestellungen von Mitarbeiter 5 abrufen:

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
quelle
1
ROW NUMBER BY PARTITION-Funktion verwendet auch eine Sortierung. Sie müssen die Tabelle sortieren, um Zeilennummern für jeden Datensatz zuzuweisen ...
Sadhir
Dies ist wahr, aber ohne eine Art von Natur funktioniert dies einfach nicht. Die beste Lösung besteht darin, die wichtigsten Spalten zu indizieren, die mit etwas wie der obigen Abfrage getroffen und ausgeführt werden.
JonVD
101

Sie können SQL Server veranlassen, die letzten N Zeilen mit diesem SQL auszuwählen:

select * from tbl_name order by id desc limit N;
Niru Mukund Shah
quelle
2
Wie wäre es mit Versionskompatibilität?
Fractaliste
62
Dies funktioniert in SQL Server nicht. Scheint wie eine MySQL-, PostgreSQL- und SQLite-Funktion.
Tim Friesen
3
Alle aufgezählten Produkte sind definitiv SQL Server. Wenn Sie über MS SQL Server sprechen möchten, warum nicht so nennen?
Gena2x
4
Ich bin verwirrt, die Frage fragt, wie eine Auswahlabfrage "ohne Verwendung von ORDER BY" erstellt werden soll, und die Auswahlabfrage in Ihrer Antwort hat "order by". Ist das eine Art "Bestellung von" ohne "Bestellung von"?
Robert Sinclair
5
@ gena2x Diese Frage ist mit SQL Server gekennzeichnet. Dieses Tag bezieht sich auf Microsoft SQL Server.
Martin Smith
51

Ich habe den Code von JonVD getestet, fand ihn aber sehr langsam, 6s.

Dieser Code dauerte 0s.

SELECT TOP(5) ORDERID, CUSTOMERID, OrderDate    
FROM Orders where EmployeeID=5    
Order By OrderDate DESC
ABI
quelle
4
Wie viele Zeilen? Wenn Sie viele Zeilen haben, die WIRKLICH langsam sein können
Diego
@Diego Warum ist das so? Wenn Sie OrderDateindiziert haben, sollte es im Wesentlichen gleich schnell sein, die ersten oder letzten N Zeilen einer Abfrage auszuwählen . Mir ist klar, dass es eine Chance gibt, die OrderDategut mit der eingefügten Reihenfolge korreliert, aber das ist bestenfalls ein Nebeneffekt und erfordert immer noch einen Tabellenscan, oder? (Und ich glaube nicht, dass es das beantwortet, worauf das OP als besser formulierten Betrüger ihrer Frage hinweist : dh ohne zu sortieren)
Ruffin
1
@Diego - Warum glaubst du, dass dies langsamer sein wird als die Antwort, die du akzeptiert hast?
Martin Smith
2
Dies gibt die Zeilen verkehrt herum zurück. Sie müssen dann bei ihnen nachbestellen, um die ursprüngliche Bestellung zurückzubekommen.
Mark
15

Wenn Sie die letzte Anzahl von Zeilen aus einer Tabelle auswählen möchten.

Die Syntax wird wie folgt sein

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

Diese Aussagen funktionieren aber auf unterschiedliche Weise. Danke Jungs.

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

Auf diese Weise können Sie die letzten 10 Zeilen erhalten, aber die Reihenfolge zeigt den absteigenden Weg

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

Ganz allgemein und zur Unterstützung von SQL Server ist hier

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

und für die Leistung ist es nicht schlecht (weniger als eine Sekunde für mehr als 10.000 Datensätze auf dem Server-Computer)

Hakan Fıstık
quelle
1
Nun, 10'000 Datensätze sind nichts, worauf Sie bei der Leistung achten sollten. Wenn Sie über Millionen von Datensätzen sprechen, können Sie über die Leistung
nachdenken
6

Ist "Id" indiziert? Wenn nicht, ist das eine wichtige Sache (ich vermute, es ist bereits indiziert).

Müssen Sie auch ALLE Spalten zurückgeben? Möglicherweise können Sie die Geschwindigkeit erheblich verbessern, wenn Sie nur eine kleinere Teilmenge von Spalten benötigen, die vom Index in der ID-Spalte VOLLSTÄNDIG berücksichtigt werden kann - z. B. wenn Sie in der ID-Spalte einen NONCLUSTERED-Index haben, ohne einen anderen Felder, die im Index enthalten sind, müssten dann nach dem Clustered-Index gesucht werden, damit der Rest der Spalten tatsächlich zurückgegeben wird. Dies könnte einen Großteil der Kosten der Abfrage ausmachen. Wenn es sich um einen CLUSTERED-Index oder einen NONCLUSTERED-Index handelt, der alle anderen Felder enthält, die Sie in der Abfrage zurückgeben möchten, sollte dies in Ordnung sein.

AdaTheDev
quelle
6

Zuerst erhalten Sie die meisten Aufzeichnungen von

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

Und dann :

In SQL Server 2012

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

In 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
quelle
4

Hier ist etwas, das Sie ohne versuchen können, order byaber ich denke, es erfordert, dass jede Zeile einzigartig ist. Nist die Anzahl der gewünschten Zeilen, List die Anzahl der Zeilen in der Tabelle.

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

Wie bereits erwähnt, ist nicht definiert, welche Zeilen zurückgegeben werden.

EDIT: das ist eigentlich Hund langsam. Wirklich wertlos.

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

Diese Abfrage gibt die letzten N Zeilen in der richtigen Reihenfolge zurück, aber die Leistung ist schlecht

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

Verwenden Sie desc mit orderby am Ende der Abfrage, um die letzten Werte abzurufen.

Sara
quelle
1

Dies passt vielleicht nicht ganz zur Frage, aber…

OFFSET-Klausel

Mit dieser OFFSET numberKlausel können Sie mehrere Zeilen überspringen und danach Zeilen zurückgeben.

Dieser Dokumentlink ist zu Postgres; Ich weiß nicht, ob dies für Sybase / MS SQL Server gilt.

Basil Bourque
quelle
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
quelle
1

MS unterstützt LIMIT in t-sql nicht. Meistens bekomme ich nur MAX (ID) und subtrahiere dann.

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

Dies gibt weniger als 10 Datensätze zurück, wenn die ID nicht sequentiell ist.

olafk
quelle
0

Eine Technik, mit der ich die aktuellsten Zeilen in sehr großen Tabellen (über 100 Millionen oder über 1 Milliarde Zeilen) abfrage, beschränkt die Abfrage darauf, nur den letzten "N" -Prozentsatz der letzten Zeilen zu "lesen". Dies sind reale Anwendungen, zum Beispiel mache ich dies für nicht historische aktuelle Wetterdaten oder aktuelle Newsfeed-Suchen oder aktuelle GPS-Standortdatenpunktdaten.

Dies ist eine enorme Leistungsverbesserung, wenn Sie sicher wissen, dass sich Ihre Zeilen beispielsweise in den letzten TOP 5% der Tabelle befinden. Selbst wenn es Indizes in den Tabellen gibt, werden die Möglichkeiten weiter auf nur 5% der Zeilen in Tabellen mit mehr als 100 Millionen oder mehr als 1 Milliarde Zeilen beschränkt. Dies ist insbesondere dann der Fall, wenn ältere Daten Lesevorgänge auf der physischen Festplatte erfordern und nicht nur logisch im Speicher Lesevorgänge im .

Dies ist weitaus effizienter als SELECT TOP | PROZENT | LIMIT, da es nicht die Zeilen auswählt, sondern lediglich den Teil der zu durchsuchenden Daten begrenzt.

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

So zeigen Sie die letzten 3 Zeilen an, ohne Folgendes zu verwenden 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
quelle
1
Dies liefert keine vorhersehbaren Ergebnisse. In den MSDN-Dokumenten von SQL Server ( msdn.microsoft.com/en-us/library/ms189463.aspx ) heißt es: "Wenn TOP in Verbindung mit der ORDER BY-Klausel verwendet wird, ist die Ergebnismenge auf die erste N bestellte Anzahl beschränkt Zeilen; andernfalls wird die erste N Anzahl von Zeilen in einer undefinierten Reihenfolge zurückgegeben. "
caveman_dick
-1

Versuchen Sie es mit der EXCEPTSyntax.
Etwas wie das:

   SELECT * 
    FROM   clientDetails 
    EXCEPT 
    (SELECT TOP (numbers of rows - how many rows you want) * 
     FROM   clientDetails) 
Mayur Godhani
quelle
Gleiche Antwort wie @Prafulla Sutradhar
DMK
-1

Vielleicht etwas spät, aber hier ist eine einfache Auswahl, die Ihre Frage löst.

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