In PostgreSQL sono presenti le parole chiave Limit
e Offset
che consentono una paginazione molto semplice dei set di risultati.
Qual è la sintassi equivalente per SQL Server?
In PostgreSQL sono presenti le parole chiave Limit
e Offset
che consentono una paginazione molto semplice dei set di risultati.
Qual è la sintassi equivalente per SQL Server?
Risposte:
L'equivalente di LIMIT
è SET ROWCOUNT
, ma se si desidera l'impaginazione generica è meglio scrivere una query come questa:
;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
Il vantaggio qui è la parametrizzazione dell'offset e del limite nel caso in cui si decida di modificare le opzioni di paginazione (o consentire all'utente di farlo).
Nota: il @Offset
parametro dovrebbe utilizzare l'indicizzazione basata su uno per questo anziché la normale indicizzazione basata su 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
ha 200k record, recupererà prima tutto, quindi applicherà il limite? Questa query è efficiente?
Questa funzionalità è ora semplificata in SQL Server 2012. Funziona da SQL Server 2012 in poi.
Limita con offset per selezionare da 11 a 20 righe in SQL Server:
SELECT email FROM emailTable
WHERE user_id=3
ORDER BY Id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
OFFSET
: numero di righe saltateNEXT
: numero richiesto di righe successiveRiferimento: https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017
SQL_CALC_FOUND_ROWS
quando si utilizza questo?
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}
Nota:
questa soluzione funzionerà solo in SQL Server 2005 o versioni successive, poiché era in quel momento che era ROW_NUMBER()
stata implementata.
AS xx
Per me l'uso di OFFSET e FETCH insieme è stato lento, quindi ho usato una combinazione di TOP e OFFSET come questa (che era più veloce):
SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname
Nota: se si utilizzano TOP e OFFSET insieme nella stessa query come:
SELECT TOP 20 columname1, columname2 FROM tablename
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS
Quindi viene visualizzato un errore, quindi per utilizzare TOP e OFFSET insieme è necessario separarlo con una query secondaria.
E se è necessario utilizzare SELECT DISTINCT, la query è simile a:
SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname
Nota: l'uso di SELECT ROW_NUMBER con DISTINCT non ha funzionato per me.
SELECT TOP 20 id FROM table1 where id > 10 order by date OFFSET 20 rows
, devi trasformarlo come SELECT TOP 20 * FROM (SELECT id FROM table1 where id > 10 order by date OFFSET 20 ROWS) t1
. Modificherò la mia risposta. Grazie e mi scusi il mio inglese.
Un altro campione:
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;
C'è qui qualcuno dire su questa funzionalità in SQL 2011, la sua triste scelgono un po 'parola chiave diversa "Offset / fetch", ma la sua non standart quindi OK.
Aggiungendo una leggera variazione alla soluzione di Aaronaught, in genere parametrizzo il numero di pagina (@PageNum) e le dimensioni della pagina (@PageSize). In questo modo ogni evento di clic sulla pagina invia semplicemente il numero di pagina richiesto insieme a una dimensione di pagina configurabile:
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
Il più vicino che potessi fare è
select * FROM( SELECT *, ROW_NUMBER() over (ORDER BY ID ) as ct from [db].[dbo].[table] ) sub where ct > fromNumber and ct <= toNumber
Che immagino simile select * from [db].[dbo].[table] LIMIT 0, 10
-- @RowsPerPage can be a fixed number and @PageNumber number can be passed
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 2
SELECT *
FROM MemberEmployeeData
ORDER BY EmployeeNumber
OFFSET @PageNumber*@RowsPerPage ROWS
FETCH NEXT 10 ROWS ONLY
@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
Poiché nessuno ha ancora fornito questo codice:
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...
Punti importanti:
@limit
può essere sostituito con il numero di risultati da recuperare,@offset
è il numero di risultati da saltarewhere
eorder by
clausole e fornirà risultati errati se non sono sincronizzatiorder by
c'è esplicitamente se questo è ciò che è necessarioIn particolare per SQL-SERVER puoi ottenerlo in molti modi diversi. Per un vero esempio abbiamo preso la tabella dei clienti qui.
Esempio 1: con "SET ROWCOUNT"
SET ROWCOUNT 10
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName
Per restituire tutte le righe, impostare ROWCOUNT su 0
SET ROWCOUNT 0
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName
Esempio 2: con "ROW_NUMBER e 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
Esempio 3: con "OFFSET e FETCH", ma con questo "ORDER BY" è obbligatorio
SELECT CustomerID, CompanyName FROM Customers
ORDER BY CompanyName
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY
Spero che questo ti aiuti.
Da allora, ho testato più volte questo script più utile di 1 milione di record ogni pagina 100 record con l'impaginazione funzionano più velocemente il mio PC esegue questo script 0 sec mentre il confronto con mysql ha il proprio limite e lo scostamento di circa 4,5 sec per ottenere il risultato.
Qualcuno potrebbe perdere la comprensione di Row_Number () ordinare sempre per campo specifico. Nel caso in cui abbiamo bisogno di definire solo la riga in sequenza dovrebbe usare:
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}
Spiegare: