it-swarm.com.de

Wie werden die untersten Zeilen ausgewählt?

Ich kann SELECT TOP (200) machen, aber warum nicht UNTEN (200)?

Nun, um nicht in die Philosophie zu kommen, was ich meine, wie kann ich das Äquivalent von TOP (200) tun, aber umgekehrt (von unten, wie man es von BOTTOM erwartet)?

85
BigOmega
SELECT
    columns
FROM
(
     SELECT TOP 200
          columns
     FROM
          My_Table
     ORDER BY
          a_column DESC
) SQ
ORDER BY
     a_column ASC
76
Tom H

Es ist nicht nötig. Sie können einen ORDER BY verwenden und die Sortierung in DESC ändern, um denselben Effekt zu erzielen.

90
Justin Ethier

Sorry, aber ich glaube nicht, dass ich meiner Meinung nach korrekte Antworten sehe. 

Die Funktion TOP x zeigt die Datensätze in undefinierter Reihenfolge. Aus dieser Definition folgt, dass eine BOTTOM-Funktion nicht definiert werden kann.

Unabhängig von Index- oder Sortierreihenfolge. Wenn Sie einen ORDER BY y DESC ausführen, erhalten Sie zuerst die Zeilen mit dem höchsten y-Wert. Wenn es sich um eine automatisch generierte ID handelt, sollten die Datensätze angezeigt werden, die der Tabelle zuletzt hinzugefügt wurden, wie in den anderen Antworten vorgeschlagen. Jedoch:

  • Dies funktioniert nur, wenn eine automatisch generierte ID-Spalte vorhanden ist
  • Wenn Sie dies mit der Funktion TOP vergleichen, hat dies erhebliche Auswirkungen auf die Leistung

Die richtige Antwort sollte sein, dass es kein Äquivalent zu TOP gibt und auch nicht geben kann, um die untersten Zeilen zu erhalten.

30
Martijn Burger

Wählen Sie Bottom 1000 von Employee aus

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 (@[email protected]) Employee.EmployeeID FROM Employee
)
14
Shadi Namrouti

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 für 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 ist es vergleichbar mit dem Hinzufügen eines where ROWNUM <(N + 1).

Jede Lösung, die eine Reihenfolge verwendet, kann Zeilen zurückgeben, die auch von der TOP-Klausel zurückgegeben werden (da dieser Datensatz an erster Stelle ungeordnet war) Nach welchen Kriterien wurde in der Bestellung von

Der Nutzen von TOP besteht darin, dass das Abrufen von Zeilen beendet wird, sobald das Dataset eine bestimmte Größe N erreicht. Sie können ein Gefühl dafür bekommen, wie die Daten aussehen, ohne sie alle abrufen zu müssen.

Um BOTTOM genau zu implementieren, müsste der gesamte Datensatz ungeordnet abgerufen und anschließend auf die letzten N Datensätze beschränkt werden. Dies ist nicht besonders effektiv, wenn Sie mit großen Tabellen arbeiten. Es wird Ihnen auch nicht unbedingt geben, was Sie denken , wonach Sie fragen. 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).

In ähnlicher Weise sind die Lösungen, die ein ORDER BY implementieren, im Umgang mit großen Datenmengen leider potenziell katastrophal. Wenn ich beispielsweise 10 Milliarden Datensätze habe und die letzten 10 haben 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, die wir beim Vergleich mit TOP haben .

Wenn Datensätze eingefügt, gelöscht, eingefügt, immer wieder gelöscht werden, werden einige Lücken im Speicher angezeigt und später, wenn möglich, Zeilen eingefügt. Was wir jedoch häufig sehen, wenn wir TOP auswählen, erscheinen als sortierte Daten , da sie möglicherweise zu einem frühen Zeitpunkt in die Existenz der Tabelle eingefügt wurden. Wenn in der Tabelle nicht viele Löschvorgänge auftreten, kann es vorkommen, dass angezeigt wird , um bestellt zu werden. (z. B. Erstellungsdaten können so weit zurückliegen wie die Tabellenerstellung selbst). In Wirklichkeit sehen die TOP N-Zeilen jedoch möglicherweise überhaupt nicht so aus, wenn es sich um eine löschlastige Tabelle handelt.

Die Quintessenz hier (Wortspiel beabsichtigt) ist also, 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.

Also - die Lösung entspricht möglicherweise den tatsächlichen Geschäftsanforderungen des Anforderers ... erfüllt jedoch nicht die Kriterien, um UNTEN zu sein.

2
user9323238

Die derzeit akzeptierte Antwort von "Justin Ethier" ist keine korrekte Antwort, wie von "Protector one" hervorgehoben.

Soweit ich sehen kann, enthält keine andere Antwort oder ein Kommentar das Äquivalent von BOTTOM (x), das der Fragesteller gestellt 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:

  • Apfel
  • orange
  • banane
  • Apfel
  • Limette

Wie Sie sehen, haben wir keine ID-Spalte. wir können nicht nach der zurückgegebenen Spalte bestellen; Die unteren beiden Datensätze können wir nicht mit Standard-SQL auswählen, wie dies für die beiden oberen Datensätze möglich ist.

Hier ist mein Versuch, eine Lösung bereitzustellen:

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.

2
tomosius

Sie müssen lediglich Ihren ORDER BY rückgängig machen. Fügen Sie DESC hinzu oder entfernen Sie sie.

2
Justin Swartsel

Die Antwort "Tom H" oben ist richtig und funktioniert für mich, wenn ich die unteren 5 Reihen bekomme.

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.

1
user3598017
SELECT TOP 10*from TABLE1 ORDER BY ID DESC

Dabei ist ID der Primärschlüssel von TABLE1.

1
Er. Binod Mehta

Das Problem bei der Bestellung ist, dass Indizes oft nicht gut genutzt werden. Es ist auch nicht sehr erweiterbar, wenn Sie 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;
1
Paul

Ich habe eine Lösung gefunden, bei der Sie nicht die Anzahl der zurückgegebenen Zeilen kennen müssen. 

Wenn Sie beispielsweise alle Standorte 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
0
Red

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

Dann ordnen Sie die Tabelle absteigend nach der Spalte RowIndex, die Sie in der Hauptabfrage erstellt haben: 

ORDER BY RowIndex DESC

Und schließlich verwenden Sie TOP mit der 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
0
Thiago Marques

Das Abfragen einer einfachen Unterabfrage, absteigend sortiert, gefolgt von einer Sortierung nach derselben Spalte, erfolgt aufsteigend.

SELECT * FROM 
    (SELECT TOP 200 * FROM [table] t2 ORDER BY t2.[column] DESC) t1
    ORDER BY t1.[column]
0
sheppe

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
0
HumbleWebDev