Antworten:
SELECT
columns
FROM
(
SELECT TOP 200
columns
FROM
My_Table
ORDER BY
a_column DESC
) SQ
ORDER BY
a_column ASC
Es ist unnötig. Sie können ein verwenden ORDER BY
und einfach die Sortierung ändern DESC
, um den gleichen Effekt zu erzielen.
Entschuldigung, aber ich glaube, ich sehe meiner Meinung nach keine richtigen Antworten.
Die TOP
x-Funktion zeigt die Datensätze in undefinierter Reihenfolge an. Aus dieser Definition folgt, dass eine BOTTOM
Funktion nicht definiert werden kann.
Unabhängig von Index oder Sortierreihenfolge. Wenn Sie dies tun, erhalten ORDER BY y DESC
Sie zuerst die Zeilen mit dem höchsten y-Wert. Wenn es sich um eine automatisch generierte ID handelt, sollten die zuletzt zur Tabelle hinzugefügten Datensätze angezeigt werden, wie in den anderen Antworten vorgeschlagen. Jedoch:
TOP
Funktion vergleichen, hat dies erhebliche Auswirkungen auf die LeistungDie richtige Antwort sollte sein, dass es kein Äquivalent zum TOP
Abrufen der unteren Zeilen gibt und auch nicht geben kann .
Logisch,
BOTTOM (x) is all the records except TOP (n - x), where n is the count; x <= n
Wählen Sie zB Bottom 1000 vom Mitarbeiter aus:
In 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
)
Es scheint, dass eine der Antworten, die eine ORDER BY-Klausel in der Lösung implementieren, den Punkt verfehlt oder nicht wirklich versteht, was TOP an Sie zurückgibt.
TOP gibt eine ungeordnete Abfrageergebnismenge zurück, die die Datensatzmenge auf die ersten N zurückgegebenen Datensätze beschränkt. (Aus Oracle-Sicht entspricht dies dem Hinzufügen eines where ROWNUM <(N + 1).
Jede Lösung, die eine Bestellung verwendet, kann Zeilen zurückgeben, die auch von der TOP-Klausel zurückgegeben werden (da dieser Datensatz überhaupt nicht geordnet war), abhängig davon, welche Kriterien in der Bestellung von verwendet wurden
Der Nutzen von TOP besteht darin, dass das Dataset keine Zeilen mehr abruft, sobald es eine bestimmte Größe N erreicht. Sie können ein Gefühl dafür bekommen, wie die Daten aussehen, ohne alle abrufen zu müssen.
Um BOTTOM genau zu implementieren, müsste der gesamte Datensatz ungeordnet abgerufen und dann auf die endgültigen N Datensätze beschränkt werden. Dies ist nicht besonders effektiv, wenn Sie mit großen Tabellen arbeiten. Es wird Ihnen auch nicht unbedingt das geben, wonach Sie zu fragen glauben . Das Ende des Datensatzes muss nicht unbedingt "die zuletzt eingefügten Zeilen" sein (und wird wahrscheinlich nicht für die meisten DML-intensiven Anwendungen sein).
Ebenso sind die Lösungen, die ein ORDER BY implementieren, beim Umgang mit großen Datenmengen leider potenziell katastrophal. Wenn ich beispielsweise 10 Milliarden Datensätze habe und die letzten 10 möchte, ist es ziemlich dumm, 10 Milliarden Datensätze zu bestellen und die letzten 10 auszuwählen.
Das Problem hierbei ist, dass BOTTOM nicht die Bedeutung hat, an die wir denken, wenn wir es mit TOP vergleichen.
Wenn Datensätze immer und immer wieder eingefügt, gelöscht, eingefügt, gelöscht werden, treten einige Lücken im Speicher auf, und später werden nach Möglichkeit Zeilen eingefügt. Was wir jedoch häufig sehen, wenn wir TOP auswählen, scheinen sortierte Daten zu sein, da sie möglicherweise schon früh in die Existenz der Tabelle eingefügt wurden. Wenn die Tabelle nicht viele Löschungen erfährt, kann es erscheinen sie geordnet zu sein. (z. B. können die Erstellungsdaten so weit zurückliegen wie die Tabellenerstellung selbst). Die Realität ist jedoch, dass wenn es sich um eine löschlastige Tabelle handelt, die TOP N-Zeilen möglicherweise überhaupt nicht so aussehen.
Das Fazit hier (Wortspiel beabsichtigt) ist, dass jemand, der nach den UNTEN N-Datensätzen fragt, nicht wirklich weiß, wonach er fragt. Oder zumindest, was sie verlangen und was UNTEN eigentlich bedeutet, ist nicht dasselbe.
Die Lösung erfüllt möglicherweise die tatsächlichen Geschäftsanforderungen des Anforderers ... erfüllt jedoch nicht die Kriterien für die UNTEN.
insert
Anweisung ausgeführt, um Zeilen in eine große, nicht indizierte Tabelle einzufügen. (Ich fülle die Tabelle zuerst auf, bevor ich mit der Indizierung beginne.) Ich habe meine Client-Sitzung aufgrund eines Neustarts oder was auch immer verloren und möchte nun sehen, ob sich meine neu hinzugefügten Zeilen dort befinden. Wenn die unterste Zeile der Tabelle eine meiner letzten ist, weiß ich, dass der Vorgang abgeschlossen ist. Wenn die 'untere' Zeile etwas anderes ist, gibt es keine Garantien und ich muss die gesamte Tabelle scannen, um sicherzugehen ... aber höchstwahrscheinlich könnte ich Zeit sparen, indem ich schnell die 'untere' überprüfe, genau wie Sie die ' oben'.
Die derzeit akzeptierte Antwort von "Justin Ethier" ist keine korrekte Antwort, wie von "Protector One" hervorgehoben.
Soweit ich sehen kann, entspricht derzeit keine andere Antwort oder kein anderer Kommentar UNTEN (x), um die der Autor der Frage gebeten hat.
Betrachten wir zunächst ein Szenario, in dem diese Funktionalität benötigt wird:
SELECT * FROM Split('apple,orange,banana,apple,lime',',')
Dies gibt eine Tabelle mit einer Spalte und fünf Datensätzen zurück:
Wie Sie sehen können: Wir haben keine ID-Spalte; Wir können nicht nach der zurückgegebenen Spalte bestellen. und wir können die beiden unteren Datensätze nicht mit Standard-SQL auswählen, wie wir es für die beiden oberen Datensätze tun können.
Hier ist mein Versuch, eine Lösung zu finden:
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
Und hier ist eine vollständigere Lösung:
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
Ich behaupte keineswegs, dass dies unter allen Umständen eine gute Idee ist, aber es liefert die gewünschten Ergebnisse.
Alles was Sie tun müssen, ist Ihre umzukehren ORDER BY
. Hinzufügen oder entfernen DESC
.
Das Problem bei der Bestellung in die andere Richtung ist, dass Indizes häufig nicht gut genutzt werden. Es ist auch nicht sehr erweiterbar, wenn Sie jemals eine Anzahl von Zeilen auswählen müssen, die nicht am Anfang oder am Ende stehen. Ein alternativer Weg ist wie folgt.
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;
Die Antwort "Tom H" oben ist korrekt und funktioniert bei mir, wenn ich die unteren 5 Zeilen erhalte.
SELECT [KeyCol1], [KeyCol2], [Col3]
FROM
(SELECT TOP 5 [KeyCol1],
[KeyCol2],
[Col3]
FROM [dbo].[table_name]
ORDER BY [KeyCol1],[KeyCol2] DESC) SOME_ALAIS
ORDER BY [KeyCol1],[KeyCol2] ASC
Vielen Dank.
Versuche dies.
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
Ich habe eine Lösung für dieses Problem gefunden, bei der Sie die Anzahl der zurückgegebenen Zeilen nicht kennen müssen.
Wenn Sie beispielsweise alle Speicherorte in einer Tabelle protokollieren möchten, mit Ausnahme der letzten 1 (oder 2, 5 oder 34)
SELECT *
FROM
(SELECT ROW_NUMBER() OVER (ORDER BY CreatedDate) AS Row, *
FROM Locations
WHERE UserId = 12345) AS SubQuery
WHERE Row > 1 -- or 2, or 5, or 34
SELECT TOP 10*from TABLE1 ORDER BY ID DESC
Wobei ID der Primärschlüssel der TABELLE1 ist.
Erstellen Sie zunächst einen Index in einer Unterabfrage gemäß der ursprünglichen Reihenfolge der Tabelle mit:
ROW_NUMBER () OVER (ORDER BY (SELECT NULL) ) AS RowIndex
Ordnen Sie dann die Tabelle nach der RowIndex
Spalte ab, die Sie in der Hauptabfrage erstellt haben:
ORDER BY RowIndex DESC
Und schließlich verwenden Sie TOP
mit Ihrer gewünschten Anzahl von Zeilen:
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