Sto cercando di fare qualcosa del tipo:
SELECT * FROM table LIMIT 10,20
o
SELECT * FROM table LIMIT 10 OFFSET 10
ma usando SQL Server
L'unico soluzione che ho trovato sembra eccessivo:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases
) a WHERE row > 5 and row <= 10
Ho anche trovato :
SELECT TOP 10 * FROM stuff;
... ma non è quello che voglio fare poiché non riesco a specificare il limite iniziale.
C'è un altro modo per farlo?
Inoltre, solo curioso, c'è un motivo per cui SQL Server non supporta la funzione LIMIT
o qualcosa di simile? Non voglio essere cattivo, ma sembra davvero qualcosa di cui un DBMS ha bisogno ... Se lo fa, allora mi dispiace di essere così ignorante! Ho lavorato con MySQL e SQL + negli ultimi 5 anni, quindi ...
La clausola LIMIT
non fa parte di SQL standard. È supportato come estensione del fornitore per SQL da MySQL, PostgreSQL e SQLite.
Altre marche di database possono avere caratteristiche simili (ad esempio TOP
in Microsoft SQL Server), ma queste non funzionano sempre in modo identico.
È difficile utilizzare TOP
in Microsoft SQL Server per imitare la clausola LIMIT
. Ci sono casi in cui semplicemente non funziona.
La soluzione che hai mostrato, usando ROW_NUMBER()
è disponibile in Microsoft SQL Server 2005 e versioni successive. Questa è la soluzione migliore (per ora) che funziona esclusivamente come parte della query.
Un'altra soluzione è utilizzare TOP
per recuperare le prime count + offset righe , quindi utilizza l'API per cercare oltre le prime offset righe.
Guarda anche:
Per SQL Server 2012 + è possibile utilizzare .
SELECT *
FROM sys.databases
ORDER BY name
OFFSET 5 ROWS
FETCH NEXT 5 ROWS ONLY
come hai trovato, questo è il metodo SQL Server preferito:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases
) a WHERE a.row > 5 and a.row <= 10
Se si utilizza il voto di SQL Server 2012+ per la risposta di Martin Smith e si utilizzano le estensioni OFFSET
e FETCH NEXT
per ORDER BY
,
Se sei abbastanza sfortunato da rimanere bloccato con una versione precedente, potresti fare qualcosa del genere,
WITH Rows AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY [dbo].[SomeColumn]) [Row]
, *
FROM
[dbo].[SomeTable]
)
SELECT TOP 10
*
FROM
Rows
WHERE Row > 10
Credo funzionalmente equivalente a
SELECT * FROM SomeTable LIMIT 10 OFFSET 10 ORDER BY SomeColumn
e il modo migliore che conosco per farlo in TSQL, prima di MS SQL 2012.
Se sono presenti molte righe, è possibile ottenere prestazioni migliori utilizzando una tabella temporanea anziché un CTE.
Sfortunatamente, ROW_NUMBER()
è il meglio che puoi fare. In realtà è più corretto, perché i risultati di una clausola limit
o top
non hanno davvero significato senza rispetto di un ordine specifico. Ma è ancora un dolore da fare.
Aggiornamento: SQL Server 2012 aggiunge una funzione simile a limit
tramite parole chiave OFFSET e FETCH . Questo è l'approccio ansi standard, al contrario di LIMIT
, che è un'estensione MySql non standard.
Cosa ne pensi di questo?
SET ROWCOUNT 10
SELECT TOP 20 *
FROM sys.databases
ORDER BY database_id DESC
Ti dà le ultime 10 righe delle prime 20 righe. Uno svantaggio è che l'ordine è invertito, ma almeno è facile da ricordare.
SELECT TOP 10 *
FROM TABLE
WHERE IDCOLUMN NOT IN (SELECT TOP 10 IDCOLUMN FROM TABLE)
Dovrebbe dare record 11-20. Probabilmente non troppo efficiente se si incrementa per ottenere ulteriori pagine, e non sono sicuro di come potrebbe essere influenzato dall'ordinamento. Potrebbe essere necessario specificarlo in entrambe le istruzioni WHERE.
Solo per la soluzione record che funziona sulla maggior parte dei motori di database potrebbe non essere la più efficiente:
Select Top (ReturnCount) *
From (
Select Top (SkipCount + ReturnCount) *
From SourceTable
Order By ReverseSortCondition
) ReverseSorted
Order By SortCondition
Nota Pelase: l'ultima pagina conterrebbe comunque le righe ReturnCount, indipendentemente da SkipCount. Ma potrebbe essere una buona cosa in molti casi.
Un buon modo è quello di creare una procedura:
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
proprio come limite 0,2 /////////////// eseguire l'impaginazione 0,4
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
Usa tutto il server SQL:; con tbl as (SELECT ROW_NUMBER () su (ordina per (seleziona 1)) come RowIndex, * dalla tabella) seleziona i primi 10 * da tbl dove RowIndex> = 10
Dalla documentazione online di MS SQL Server ( http://technet.Microsoft.com/en-us/library/ms186734.aspx ), ecco il loro esempio che ho testato e funziona, per recuperare un set specifico di righe. ROW_NUMBER richiede un OVER, ma puoi ordinare come preferisci:
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;
Finora questo formato è ciò che funziona per me (non la migliore performance però):
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}
Una nota a lato, l'impaginazione su dati dinamici può portare a risultati strani/imprevisti.
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
Stampa le righe da 10 a 15.