it-swarm.com.de

Zeilenversatz in SQL Server

Gibt es eine Möglichkeit in SQL Server, die Ergebnisse ab einem bestimmten Offset zu erhalten? In einer anderen Art von SQL-Datenbank können Sie beispielsweise Folgendes tun:

SELECT * FROM MyTable OFFSET 50 LIMIT 25

um die Ergebnisse 51-75 zu erhalten. Dieses Konstrukt scheint in SQL Server nicht vorhanden zu sein. 

Wie kann ich das erreichen, ohne alle Zeilen zu laden, die mir egal sind? Vielen Dank! 

124
Alex

Ich würde SELECT * vermeiden. Geben Sie die Spalten an, die Sie tatsächlich benötigen, auch wenn es sich um alle handelt.

SQL Server 2005+

SELECT col1, col2 
FROM (
    SELECT col1, col2, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum
    FROM MyTable
) AS MyDerivedTable
WHERE MyDerivedTable.RowNum BETWEEN @startRow AND @endRow

SQL Server 2000

Durch große Ergebnismengen in SQL Server 2000 effizient auslagern

Eine effizientere Methode zum Durchblättern großer Ergebnismengen

150
Brian Kim

Wenn Sie alle Seiten in der richtigen Reihenfolge bearbeiten, können Sie sich einfach den letzten Schlüsselwert merken, der auf der vorherigen Seite angezeigt wurde, und TOP (25) ... WHERE Key > @last_key ORDER BY Key kann die beste Methode sein, wenn geeignete Indizes vorhanden sind, die eine effiziente Suche ermöglichen - oder ein API-Cursor . wenn nicht.

Für die Auswahl einer beliebigen Seite ist die beste Lösung für SQL Server 2005 - 2008 R2 wahrscheinlich ROW_NUMBER und BETWEEN.

Für SQL Server 2012 und höher können Sie für diese Anforderung die erweiterte Klausel ORDER BY verwenden.

SELECT  *
FROM     MyTable 
ORDER BY OrderingColumn ASC 
OFFSET  50 ROWS 
FETCH NEXT 25 ROWS ONLY 

Obwohl bleibt abzuwarten, wie gut diese Option ausgeführt wird .

94
Martin Smith

Dies ist eine Möglichkeit (SQL2000)

SELECT * FROM
(
    SELECT TOP (@pageSize) * FROM
    (
        SELECT TOP (@pageNumber * @pageSize) *
        FROM tableName 
        ORDER BY columnName ASC
    ) AS t1 
    ORDER BY columnName DESC
) AS t2 
ORDER BY columnName ASC

und das ist ein anderer Weg (SQL 2005)

;WITH results AS (
    SELECT 
        rowNo = ROW_NUMBER() OVER( ORDER BY columnName ASC )
        , *
    FROM tableName 
) 
SELECT * 
FROM results
WHERE rowNo between (@pageNumber-1)*@pageSize+1 and @pageNumber*@pageSize
22
leoinfo

Sie können die Funktion ROW_NUMBER() verwenden, um das zu erhalten, was Sie möchten:

SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY id) RowNr, id FROM tbl) t
WHERE RowNr BETWEEN 10 AND 20
10
Matthias Meid

Es gibt OFFSET .. FETCH in SQL Server 2012, Sie müssen jedoch eine ORDER BY-Spalte angeben.

Wenn Sie wirklich keine explizite Spalte haben, die Sie als ORDER BY-Spalte übergeben könnten (wie von anderen vorgeschlagen), können Sie diesen Trick verwenden:

SELECT * FROM MyTable 
ORDER BY @@VERSION 
OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY

... oder

SELECT * FROM MyTable 
ORDER BY (SELECT 0)
OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY

Wir verwenden es in jOOQ , wenn Benutzer eine Bestellung nicht explizit angeben. Dies führt dann zu ziemlich zufälligen Bestellungen ohne zusätzliche Kosten.

6
Lukas Eder

Für Tabellen mit mehr und großen Datenspalten ziehe ich Folgendes vor:

SELECT 
  tablename.col1,
  tablename.col2,
  tablename.col3,
  ...
FROM
(
  (
    SELECT
      col1
    FROM 
    (
      SELECT col1, ROW_NUMBER() OVER (ORDER BY col1 ASC) AS RowNum
      FROM tablename
      WHERE ([CONDITION])
    )
    AS T1 WHERE T1.RowNum BETWEEN [OFFSET] AND [OFFSET + LIMIT]
  )
  AS T2 INNER JOIN tablename ON T2.col1=tablename.col1
);

-

[CONDITION] can contain any WHERE clause for searching.
[OFFSET] specifies the start,
[LIMIT] the maximum results.

Bei Tabellen mit großen Daten wie BLOBs ist die Leistung wesentlich besser, da die ROW_NUMBER-Funktion nur eine Spalte durchsehen muss und nur die übereinstimmenden Zeilen mit allen Spalten zurückgegeben werden.

6
Arthur van Dijk

Siehe meine Auswahl für Paginator

SELECT TOP @limit * FROM (
   SELECT ROW_NUMBER() OVER (ORDER BY colunx ASC) offset, * FROM (

     -- YOU SELECT HERE
     SELECT * FROM mytable


   ) myquery
) paginator
WHERE offset > @offset

Das löst die Paginierung;)

5
PerfectLion
SELECT TOP 75 * FROM MyTable
EXCEPT 
SELECT TOP 50 * FROM MyTable
3
Jithin Shaji

Im Folgenden werden 25 Datensätze ohne die ersten 50 Datensätze angezeigt, die in SQL Server 2012 ausgeführt wurden.

SELECT * FROM MyTable ORDER BY ID OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY;

sie können die ID als Anforderung ersetzen

2
Shb

Abhängig von Ihrer Version können Sie dies nicht direkt tun, aber Sie könnten auch etwas Hackeriges tun

select top 25 *
from ( 
  select top 75 *
  from   table 
  order by field asc
) a 
order by field desc 

wobei "Feld" der Schlüssel ist. 

2
Unsliced

Sie sollten vorsichtig sein, wenn Sie die Anweisung row_number () OVER (ORDER BY) verwenden, da Performane ziemlich schlecht ist. Dasselbe gilt für die Verwendung von Common Table Expressions mit row_number (), die noch schlimmer ist. Ich verwende das folgende Snippet, das sich als etwas schneller erwies als eine Tabellenvariable mit einer Identität, um die Seitennummer anzugeben.

DECLARE @Offset INT = 120000
DECLARE @Limit INT = 10

DECLARE @ROWCOUNT INT = @[email protected]
SET ROWCOUNT @ROWCOUNT

SELECT * FROM MyTable INTO #ResultSet
WHERE MyTable.Type = 1

SELECT * FROM
(
    SELECT *, ROW_NUMBER() OVER(ORDER BY SortConst ASC) As RowNumber FROM
    (
        SELECT *, 1 As SortConst FROM #ResultSet
    ) AS ResultSet
) AS Page
WHERE RowNumber BETWEEN @Offset AND @ROWCOUNT

DROP TABLE #ResultSet
2
Patrik Melander

Ich benutze diese Technik zur Paginierung. Ich hole nicht alle Reihen. Wenn meine Seite beispielsweise die ersten 100 Zeilen anzeigen muss, hole ich nur die 100 mit where-Klausel ab. Die Ausgabe der SQL sollte einen eindeutigen Schlüssel haben.

Die Tabelle hat folgendes:

ID, KeyId, Rank

Derselbe Rang wird für mehr als eine KeyId zugewiesen.

SQL ist select top 2 * from Table1 where Rank >= @Rank and ID > @Id

Zum ersten Mal übergebe ich 0 für beide. Der zweite Durchgang 1 & 14. 3. Durchgang 2 und 6 ....

Der Wert des 10. Datensatzes Rank & Id wird an den nächsten übergeben

11  21  1
14  22  1
7   11  1
6   19  2
12  31  2
13  18  2

Dies wird das System am wenigsten belasten

1
Ravi Ramaswamy

In SqlServer2005 können Sie Folgendes tun:

DECLARE @Limit INT
DECLARE @Offset INT
SET @Offset = 120000
SET @Limit = 10

SELECT 
    * 
FROM
(
   SELECT 
       row_number() 
   OVER 
      (ORDER BY column) AS rownum, column2, column3, .... columnX
   FROM   
     table
) AS A
WHERE 
 A.rownum BETWEEN (@Offset) AND (@Offset + @Limit-1) 
1
Aheho

Ich habe schon lange nach dieser Antwort gesucht (nach generischen Abfragen) und habe auf SQL Server 2000+ mit ROWCOUNT und Cursorn und ohne TOP oder eine temporäre Tabelle eine andere Möglichkeit gefunden.

Mit dem SET ROWCOUNT [OFFSET+LIMIT] können Sie die Ergebnisse einschränken. Mit den Cursorn können Sie direkt zu der gewünschten Zeile gehen und dann bis zum Ende durchlaufen.

Ihre Anfrage wäre also so:

SET ROWCOUNT 75 -- (50 + 25)
DECLARE MyCursor SCROLL CURSOR FOR SELECT * FROM pessoas
OPEN MyCursor
FETCH ABSOLUTE 50 FROM MyCursor -- OFFSET
WHILE @@FETCH_STATUS = 0 BEGIN
    FETCH next FROM MyCursor
END
CLOSE MyCursor
DEALLOCATE MyCursor
SET ROWCOUNT 0
0
Capilé

Der beste Weg, dies zu tun, ohne Zeit zu verschwenden, um Datensätze zu bestellen, ist wie folgt:

select 0 as tmp,Column1 from Table1 Order by tmp OFFSET 5000000 ROWS FETCH NEXT 50 ROWS ONLY

es dauert weniger als eine sekunde!
beste lösung für große tische.

0
Pishgaman.org

Der einfachste Weg wäre

SELECT * FROM table ORDER BY OrderColumn ASC LIMIT 50,25;

Dies funktioniert in MySQL und (glaube ich) in anderen SQL-Datenbanken.

0
DataDeer.net