web-dev-qa-db-de.com

LIMIT 10..20 in SQL Server

Ich versuche etwas zu tun wie:

SELECT * FROM table LIMIT 10,20

oder

SELECT * FROM table LIMIT 10 OFFSET 10

aber mit SQL Server

Das einzige Lösung, die ich gefunden habe sieht aus wie Overkill:

SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases 
 ) a WHERE row > 5 and row <= 10

Ich habe auch gefunden :

SELECT TOP 10 * FROM stuff; 

... aber es ist nicht das, was ich tun möchte, da ich das Startlimit nicht festlegen kann.

Gibt es eine andere Möglichkeit für mich, das zu tun?

Neugierig, gibt es auch einen Grund, warum SQL Server die Funktion LIMIT oder ähnliches nicht unterstützt? Ich möchte nicht gemein sein, aber das hört sich wirklich nach etwas an, das ein DBMS braucht ... Wenn ja, dann tut es mir leid, dass ich so ignorant bin! Ich habe in den letzten 5 Jahren mit MySQL und SQL + gearbeitet, also ...

154
marcgg

Die LIMIT -Klausel ist nicht Teil von Standard-SQL. Es wird von MySQL, PostgreSQL und SQLite als Herstellererweiterung für SQL unterstützt.

Andere Datenbankmarken verfügen möglicherweise über ähnliche Funktionen (z. B. TOP in Microsoft SQL Server), diese funktionieren jedoch nicht immer identisch.

Es ist schwierig, TOP in Microsoft SQL Server zu verwenden, um die LIMIT -Klausel nachzuahmen. Es gibt Fälle, in denen es einfach nicht funktioniert.

Die von Ihnen mit ROW_NUMBER() gezeigte Lösung ist in Microsoft SQL Server 2005 und höher verfügbar. Dies ist (vorerst) die beste Lösung, die nur als Teil der Abfrage funktioniert.

Eine andere Lösung besteht darin, TOP zu verwenden, um die erste Anzahl + versetzter Zeilen abzurufen und dann die API zu verwenden Suchen Sie nach den ersten versetzten Zeilen.

Siehe auch:

100
Bill Karwin

Für SQL Server 2012 + Sie können verwenden .

SELECT  *
FROM     sys.databases
ORDER BY name 
OFFSET  5 ROWS 
FETCH NEXT 5 ROWS ONLY 
125
Martin Smith

wie Sie festgestellt haben, ist dies die bevorzugte SQL Server-Methode:

SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases 
 ) a WHERE a.row > 5 and a.row <= 10
35
KM.

Wenn Sie SQL Server 2012+ verwenden, stimmen Sie für Martin Smiths Antwort und verwenden Sie die Zeichen OFFSET und FETCH NEXT Erweiterungen zu ORDER BY,

Wenn Sie das Pech haben, mit einer früheren Version nicht mehr weiterkommen zu können, können Sie Folgendes tun:

WITH Rows AS
(
    SELECT
              ROW_NUMBER() OVER (ORDER BY [dbo].[SomeColumn]) [Row]
            , *
        FROM
              [dbo].[SomeTable]
)
SELECT TOP 10
          *
     FROM
         Rows
    WHERE Row > 10

Ich glaube, ist funktional äquivalent zu

SELECT * FROM SomeTable LIMIT 10 OFFSET 10 ORDER BY SomeColumn

und die beste Methode, die ich kenne, um dies in TSQL vor MS SQL 2012 zu tun.


Bei sehr vielen Zeilen erzielen Sie möglicherweise eine bessere Leistung, wenn Sie eine temporäre Tabelle anstelle eines CTE verwenden.

10
Jodrell

Leider ist die Funktion ROW_NUMBER() das Beste, was Sie tun können. Es ist tatsächlich korrekter, da die Ergebnisse einer limit - oder top -Klausel ohne Berücksichtigung einer bestimmten Reihenfolge keine wirkliche Bedeutung haben. Aber es ist immer noch ein Schmerz zu tun.

Update: SQL Server 2012 fügt eine limit-ähnliche Funktion über OFFSET- und FETCH-Schlüsselwörter hinzu. Dies ist der Ansi-Standard-Ansatz im Gegensatz zu LIMIT, einer nicht standardmäßigen MySql-Erweiterung.

7
Joel Coehoorn

Wie wäre es damit?

SET ROWCOUNT 10 

SELECT TOP 20 *
FROM sys.databases
ORDER BY database_id DESC

Es gibt Ihnen die letzten 10 Zeilen der ersten 20 Zeilen. Ein Nachteil ist, dass die Reihenfolge umgekehrt ist, aber zumindest ist es leicht zu merken.

5
David Patrick
SELECT TOP 10 *
FROM TABLE
WHERE IDCOLUMN NOT IN (SELECT TOP 10 IDCOLUMN FROM TABLE)

Sollte Aufzeichnungen 11-20 geben. Wahrscheinlich nicht zu effizient, wenn Sie die Anzahl erhöhen, um weitere Seiten zu erhalten, und nicht sicher sind, wie sich dies auf die Bestellung auswirken könnte. Möglicherweise muss dies in beiden WHERE-Anweisungen angegeben werden.

2
Andy

Nur für die Datensatzlösung, die in den meisten Datenbankmodulen funktioniert, ist sie möglicherweise nicht die effizienteste:

Select Top (ReturnCount) *
From (
    Select Top (SkipCount + ReturnCount) *
    From SourceTable
    Order By ReverseSortCondition
) ReverseSorted
Order By SortCondition

Hinweis: Die letzte Seite enthält weiterhin ReturnCount-Zeilen, unabhängig davon, was SkipCount ist. Aber das könnte in vielen Fällen gut sein.

1
Y.B.

Ein guter Weg ist, eine Prozedur zu erstellen:

create proc pagination (@startfrom int ,@endto int) as
SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name desc) as row FROM sys.databases 
 ) a WHERE a.row > @startfrom and a.row <= @endto

genau wie limit 0,2 /////////////// Paginierung ausführen 0,4

1
Wahaj Latif

Das Äquivalent zu LIMIT ist SET ROWCOUNT, aber wenn Sie eine generische Paginierung wünschen, ist es besser, eine Abfrage wie die folgende zu schreiben:

;WITH Results_CTE AS
(
    SELECT
        Col1, Col2, ...,
        ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
    FROM Table
    WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= @Offset
AND RowNum < @Offset + @Limit
1

Verwenden Sie alle SQL-Server:; mit tbl als (SELECT ROW_NUMBER () über (order by (select 1)) als RowIndex, * from table) Wählen Sie Top 10 * von tbl, wobei RowIndex> = 10

0

In der MS SQL Server-Onlinedokumentation ( http://technet.Microsoft.com/en-us/library/ms186734.aspx ) ist das von mir getestete und funktionierende Beispiel zum Abrufen eines bestimmte Reihe von Zeilen. ROW_NUMBER erfordert ein OVER, aber Sie können nach Belieben bestellen:

WITH OrderedOrders AS
(
  SELECT SalesOrderID, OrderDate,
  ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
  FROM Sales.SalesOrderHeader 
) 
SELECT SalesOrderID, OrderDate, RowNumber  
FROM OrderedOrders 
WHERE RowNumber BETWEEN 50 AND 60;
0
Shannon WM

Bisher funktioniert dieses Format für mich (allerdings nicht die beste Leistung):

SELECT TOP {desired amount of rows} * 
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY {order columns} asc)__row__ FROM {table})tmp
WHERE __row__ > {offset row count}

Ein Hinweis auf der Seite, der über dynamische Daten paginiert, kann zu seltsamen/unerwarteten Ergebnissen führen.

0
select * from (select id,name,ROW_NUMBER() OVER (ORDER BY id  asc) as row
from tableName1) tbl1
where tbl1.row>=10 and tbl1.row<=15

Druckt Zeilen von 10 bis 15.

0
sjith