2009-11-16 17 views
88

Qual è l'equivalente SQL del metodo .Skip() in LINQ?Come scrivere LINQ's .Skip (1000) .Take (100) in puro SQL?

Ad esempio: Vorrei selezionare le righe 1000-1100 da una tabella di database specifica.

Ciò è possibile solo con SQL? O devo selezionare l'intera tabella, quindi trovare le righe in memoria? Preferirei evitare questo, se possibile, dal momento che il tavolo può essere abbastanza grande.

risposta

75

In SQL Server 2005 e versioni successive è possibile utilizzare la funzione ROW_NUMBER. per esempio.

USE AdventureWorks; 
GO 
WITH OrderedOrders AS 
(
    SELECT SalesOrderID, OrderDate, 
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber' 
    FROM Sales.SalesOrderHeader 
) 
SELECT * 
FROM OrderedOrders 
WHERE RowNumber BETWEEN 51 AND 60; --BETWEEN is inclusive 
+0

Vedere il collegamento nella mia risposta per ulteriori dettagli. http://stackoverflow.com/questions/1744802/is-there-a-sql-equivilant-to-linq-skip1000-take100/1744815#1744815 –

+0

TRA 51 E 60 - è inclusivo. –

+0

Ma questo prima selezionerà tutto e quindi da quella selezione prenderà solo 10 a destra? O la prima query/vista avrà già solo 10? – JedatKinports

2

No, ma è possibile emulate MySQL's LIMIT clause (collegamento Overflow stack) per ottenere lo stesso risultato.

+1

risposta accettata non punta a un interessante collegamento CodeProject, ["Paging di grandi set di risultati in ASP.NET"] (http://www.codeproject.com/Articles/6936/Paging-of-Large-Resultsets-in-ASP-N ET) (più orientato a SQL rispetto al nome suggerisce). – ruffin

3

fare questo:

Run .Skip (1000) .Prendere (100) su un LINQ to SQL DataContext e guardare l'uscita di SQL. Genererà una dichiarazione SQL per te che fa ciò che stai descrivendo.

Non sarà elegante ma ha il compito.

+2

Non quello che veniva chiesto. – RayLoveless

21

LINQ to SQL fa questo utilizzando una funzione ROW_NUMBER finestre:

SELECT a,b,c FROM 
    (SELECT a,b,c, ROW_NUMBER() OVER (ORDER BY ...) as row_number 
    FROM Table) t0 
    WHERE to.row_number BETWEEN 1000 and 1100; 

questo funziona, ma la necessità di fabbricare il row_number dal ORDER BY può risultato nella query da ordinare sul lato server e causare problemi di prestazioni. Anche quando un indice può soddisfare il requisito ORDER BY, la query deve ancora contare 1000 righe prima di iniziare a restituire i risultati. Troppo spesso gli sviluppatori dimenticano questo e basta lanciare un controllo di paginazione su una tabella di 5 mil righe e chiedersi perché la prima pagina viene restituita molto più velocemente dell'ultima ...

Tuttavia, utilizzando ROW_NUMBER() è probabilmente il miglior equilibrio tra facilità d'uso e buone prestazioni, a patto di essere sicuri di evitare l'ordinamento (la condizione ORDER BY può essere soddisfatta da un indice).

+1

Grazie per le informazioni sulle prestazioni extra, dovrai fare attenzione e testarlo. – Ray

+0

Testato e per la mia tabella da mezzo milione di righe, quest'ultima pagina è circa 7 volte più lenta della prima pagina. Non ideale, ma accettabile per me. – Ray

129

SQL Server 2012 e, soprattutto, hanno aggiunto la seguente sintassi:

SELECT * 
FROM Sales.SalesOrderHeader 
ORDER BY OrderDate 
OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY 
+9

Nota che è necessario utilizzare ORDER BY ___ per utilizzare il comando OFFSET ....non che tu debba mai provare a impaginare senza un ordine. –

4

provare questo:

select * from [Table-Name] order by [Column-Name] 
offset [Skip-Count] rows 
FETCH NEXT [Take-Count] rows only 

Esempio:

select * from Personals order by Id 
offset 10 rows   --------->Skip 10 
FETCH NEXT 15 rows only --------->Take 15 
Problemi correlati