W PostgreSQL są słowa kluczowe Limit
i, Offset
które pozwolą na bardzo łatwe paginowanie zbiorów wynikowych.
Jaka jest równoważna składnia dla programu SQL Server?
W PostgreSQL są słowa kluczowe Limit
i, Offset
które pozwolą na bardzo łatwe paginowanie zbiorów wynikowych.
Jaka jest równoważna składnia dla programu SQL Server?
Odpowiedzi:
Odpowiednik LIMIT
is SET ROWCOUNT
, ale jeśli chcesz mieć ogólną paginację, lepiej napisać takie zapytanie:
;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
Zaletą jest tutaj parametryzacja przesunięcia i limitu w przypadku, gdy zdecydujesz się zmienić opcje stronicowania (lub zezwolisz na to użytkownikowi).
Uwaga:@Offset
parametr powinien używać jednej opartej indeksowanie za to zamiast normalnego indeksowania opartego na zero.
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
ma 200k rekordów, najpierw pobierze wszystkie, a potem zastosuje limit? Czy to zapytanie jest wydajne?
Ta funkcja jest teraz uproszczona w programie SQL Server 2012. Działa od wersji SQL Server 2012.
Ogranicz z przesunięciem, aby wybrać od 11 do 20 wierszy w programie SQL Server:
SELECT email FROM emailTable
WHERE user_id=3
ORDER BY Id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
OFFSET
: liczba pominiętych wierszyNEXT
: wymagana liczba następnych rzędówSQL_CALC_FOUND_ROWS
gdy używasz tego?
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}
Uwaga:
to rozwiązanie będzie działać tylko w SQL Server 2005 lub nowszym, ponieważ wtedy ROW_NUMBER()
zostało wdrożone.
AS xx
Dla mnie użycie OFFSET i FETCH razem było powolne, więc użyłem kombinacji TOP i OFFSET w ten sposób (który był szybszy):
SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname
Uwaga: jeśli używasz jednocześnie TOP i OFFSET w tym samym zapytaniu, na przykład:
SELECT TOP 20 columname1, columname2 FROM tablename
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS
Następnie pojawia się błąd, więc aby użyć GÓRA i PRZESUNIĘCIE razem, musisz je oddzielić zapytaniem podrzędnym.
A jeśli potrzebujesz użyć polecenia SELECT DISTINCT, zapytanie wygląda następująco:
SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname
Uwaga: użycie SELECT ROW_NUMBER z DISTINCT nie działa dla mnie.
SELECT TOP 20 id FROM table1 where id > 10 order by date OFFSET 20 rows
, musisz go przekształcić w ten sposób SELECT TOP 20 * FROM (SELECT id FROM table1 where id > 10 order by date OFFSET 20 ROWS) t1
. Zmienię odpowiedź. Dziękuję i wybacz mi mój angielski.
Kolejna próbka:
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;
Jest tutaj ktoś, kto mówi o tej funkcji w sql 2011, to smutne, że wybrali trochę inne słowo kluczowe "OFFSET / FETCH", ale nie jest to standard, wtedy ok.
Dodając niewielką różnicę w rozwiązaniu Aaronaught, zwykle parametryzuję numer strony (@PageNum) i rozmiar strony (@PageSize). W ten sposób każde zdarzenie kliknięcia strony wysyła po prostu żądany numer strony wraz z konfigurowalnym rozmiarem strony:
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
Najbliżej mogłem zrobić
select * FROM( SELECT *, ROW_NUMBER() over (ORDER BY ID ) as ct from [db].[dbo].[table] ) sub where ct > fromNumber and ct <= toNumber
Który chyba podobny 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
Ponieważ nikt jeszcze nie podał tego kodu:
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...
Ważne punkty:
@limit
można zastąpić liczbą wyników do pobrania,@offset
to liczba wyników do pominięciawhere
i order by
klauzulami i zapewni nieprawidłowe wyniki, jeśli nie są zsynchronizowaneorder by
jest wyraźnie, jeśli jest to potrzebneSpecyficznie dla SQL-SERVER można to osiągnąć na wiele różnych sposobów, dla przykładu wzięliśmy tutaj tabelę Customer.
Przykład 1: z „USTAW ROWCOUNT”
SET ROWCOUNT 10
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName
Aby zwrócić wszystkie wiersze, ustaw ROWCOUNT na 0
SET ROWCOUNT 0
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName
Przykład 2: z „ROW_NUMBER i 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
Przykład 3: Z „OFFSET and FETCH”, ale z tym „ORDER BY” jest obowiązkowe
SELECT CustomerID, CompanyName FROM Customers
ORDER BY CompanyName
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY
Mam nadzieję, że to ci pomoże.
Ponieważ testuję więcej razy, ten skrypt jest bardziej przydatny o 1 milion rekordów na każdej stronie. 100 rekordów z paginacją działa szybciej mój komputer wykonuje ten skrypt 0 sekund, podczas gdy w porównaniu z mysql ma własny limit i przesunięcie około 4,5 sekundy, aby uzyskać wynik.
Ktoś może nie zrozumieć, że Row_Number () zawsze sortuje według określonego pola. W przypadku, gdy musimy zdefiniować tylko wiersz w sekwencji, należy użyć:
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}
Wyjaśnić: