In PostgreSQL gibt es die Schlüsselwörter Limit
und, Offset
die eine sehr einfache Paginierung von Ergebnismengen ermöglichen.
Was ist die äquivalente Syntax für SQL Server?
In PostgreSQL gibt es die Schlüsselwörter Limit
und, Offset
die eine sehr einfache Paginierung von Ergebnismengen ermöglichen.
Was ist die äquivalente Syntax für SQL Server?
Antworten:
Das Äquivalent zu LIMIT
ist SET ROWCOUNT
, aber wenn Sie eine generische Paginierung wünschen, ist es besser, eine Abfrage wie folgt 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
Der Vorteil hierbei ist die Parametrisierung des Versatzes und des Grenzwerts für den Fall, dass Sie Ihre Paging-Optionen ändern (oder dem Benutzer dies erlauben).
Hinweis: Der @Offset
Parameter sollte hierfür eine einbasierte Indizierung anstelle der normalen nullbasierten Indizierung verwenden.
WHERE RowNum >= (@Offset + 1)
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified
. MSSQL2008 R2.
Table
Datensatz 200.000 Datensätze hat, werden alle zuerst abgerufen und dann das Limit angewendet? Ist diese Abfrage effizient?
Diese Funktion ist jetzt in SQL Server 2012 vereinfacht. Dies funktioniert ab SQL Server 2012.
Mit Versatz begrenzen, um 11 bis 20 Zeilen in SQL Server auszuwählen:
SELECT email FROM emailTable
WHERE user_id=3
ORDER BY Id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
OFFSET
: Anzahl der übersprungenen ZeilenNEXT
: erforderliche Anzahl der nächsten ZeilenSQL_CALC_FOUND_ROWS
dazu?
select top {LIMIT HERE} * from (
select *, ROW_NUMBER() over (order by {ORDER FIELD}) as r_n_n
from {YOUR TABLES} where {OTHER OPTIONAL FILTERS}
) xx where r_n_n >={OFFSET HERE}
Ein Hinweis:
Diese Lösung funktioniert nur in SQL Server 2005 oder höher, da dies der Zeitpunkt ROW_NUMBER()
war, an dem sie implementiert wurde.
AS xx
Sie können ROW_NUMBER in einem allgemeinen Tabellenausdruck verwenden, um dies zu erreichen.
;WITH My_CTE AS
(
SELECT
col1,
col2,
ROW_NUMBER() OVER(ORDER BY col1) AS row_number
FROM
My_Table
WHERE
<<<whatever>>>
)
SELECT
col1,
col2
FROM
My_CTE
WHERE
row_number BETWEEN @start_row AND @end_row
Für mich war die Verwendung von OFFSET und FETCH zusammen langsam, daher habe ich eine Kombination aus TOP und OFFSET wie diese verwendet (die schneller war):
SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname
Hinweis: Wenn Sie TOP und OFFSET zusammen in derselben Abfrage verwenden wie:
SELECT TOP 20 columname1, columname2 FROM tablename
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS
Dann erhalten Sie eine Fehlermeldung. Um TOP und OFFSET zusammen zu verwenden, müssen Sie sie durch eine Unterabfrage trennen.
Und wenn Sie SELECT DISTINCT verwenden müssen, lautet die Abfrage wie folgt:
SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname
Hinweis: Die Verwendung von SELECT ROW_NUMBER mit DISTINCT hat bei mir nicht funktioniert.
SELECT TOP 20 id FROM table1 where id > 10 order by date OFFSET 20 rows
, müssen Sie es wie transformieren SELECT TOP 20 * FROM (SELECT id FROM table1 where id > 10 order by date OFFSET 20 ROWS) t1
. Ich werde meine Antwort bearbeiten. Danke und entschuldige mein Englisch.
Ein weiteres Beispiel:
declare @limit int
declare @offset int
set @offset = 2;
set @limit = 20;
declare @count int
declare @idxini int
declare @idxfim int
select @idxfim = @offset * @limit
select @idxini = @idxfim - (@limit-1);
WITH paging AS
(
SELECT
ROW_NUMBER() OVER (order by object_id) AS rowid, *
FROM
sys.objects
)
select *
from
(select COUNT(1) as rowqtd from paging) qtd,
paging
where
rowid between @idxini and @idxfim
order by
rowid;
Es gibt hier jemanden, der über diese Funktion in SQL 2011 erzählt. Es ist traurig, dass er ein etwas anderes Schlüsselwort "OFFSET / FETCH" gewählt hat, aber es ist nicht Standard, dann ok.
Ich füge eine geringfügige Variation der Aaronaught-Lösung hinzu und parametrisiere normalerweise die Seitenzahl (@PageNum) und die Seitengröße (@PageSize). Auf diese Weise sendet jedes Seitenklickereignis nur die angeforderte Seitenzahl zusammen mit einer konfigurierbaren Seitengröße:
begin
with My_CTE as
(
SELECT col1,
ROW_NUMBER() OVER(ORDER BY col1) AS row_number
FROM
My_Table
WHERE
<<<whatever>>>
)
select * from My_CTE
WHERE RowNum BETWEEN (@PageNum - 1) * (@PageSize + 1)
AND @PageNum * @PageSize
end
Das nächste, was ich machen könnte, ist
select * FROM( SELECT *, ROW_NUMBER() over (ORDER BY ID ) as ct from [db].[dbo].[table] ) sub where ct > fromNumber and ct <= toNumber
Was ich ähnlich denke select * from [db].[dbo].[table] LIMIT 0, 10
@nombre_row :nombre ligne par page
@page:numero de la page
//--------------code sql---------------
declare @page int,@nombre_row int;
set @page='2';
set @nombre_row=5;
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY etudiant_ID ) AS RowNum, *
FROM etudiant
) AS RowConstrainedResult
WHERE RowNum >= ((@page-1)*@nombre_row)+1
AND RowNum < ((@page)*@nombre_row)+1
ORDER BY RowNum
Da noch niemand diesen Code zur Verfügung gestellt hat:
SELECT TOP @limit f1, f2, f3...
FROM t1
WHERE c1 = v1, c2 > v2...
AND
t1.id NOT IN
(SELECT TOP @offset id
FROM t1
WHERE c1 = v1, c2 > v2...
ORDER BY o1, o2...)
ORDER BY o1, o2...
Wichtige Punkte:
@limit
kann durch die Anzahl der abzurufenden Ergebnisse ersetzt werden.@offset
ist die Anzahl der zu überspringenden Ergebnissewhere
und order by
Klauseln und liefert falsche Ergebnisse, wenn sie nicht synchron sindorder by
gibt es explizit, wenn es das ist, was benötigt wirdSpeziell für SQL-SERVER können Sie dies auf viele verschiedene Arten erreichen. Als Beispiel haben wir hier die Kundentabelle genommen.
Beispiel 1: Mit "SET ROWCOUNT"
SET ROWCOUNT 10
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName
Um alle Zeilen zurückzugeben, setzen Sie ROWCOUNT auf 0
SET ROWCOUNT 0
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName
Beispiel 2: Mit "ROW_NUMBER and OVER"
With Cust AS
( SELECT CustomerID, CompanyName,
ROW_NUMBER() OVER (order by CompanyName) as RowNumber
FROM Customers )
select *
from Cust
Where RowNumber Between 0 and 10
Beispiel 3: Mit "OFFSET and FETCH", aber mit diesem "ORDER BY" ist obligatorisch
SELECT CustomerID, CompanyName FROM Customers
ORDER BY CompanyName
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY
Hoffe das hilft dir.
Da ich dieses Skript öfter teste, um 1 Million Datensätze auf jeder Seite 100 Datensätze mit Paginierung schneller zu arbeiten, führt mein PC dieses Skript 0 Sekunden lang aus, während der Vergleich mit MySQL ein eigenes Limit hat und etwa 4,5 Sekunden versetzt, um das Ergebnis zu erhalten.
Jemand versteht möglicherweise nicht, dass Row_Number () immer nach bestimmten Feldern sortiert ist. Falls wir nur eine Zeile nacheinander definieren müssen, sollten Sie Folgendes verwenden:
SELECT TOP {LIMIT} * FROM (
SELECT TOP {LIMIT} + {OFFSET} ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ROW_NO,*
FROM {TABLE_NAME}
) XX WHERE ROW_NO > {OFFSET}
Erklären: