¿Cómo escribo .Skip (1000) .Take (100) de LINQ en SQL puro?


93

¿Cuál es el equivalente SQL del .Skip()método en LINQ?

Por ejemplo: me gustaría seleccionar las filas 1000-1100 de una tabla de base de datos específica.

¿Es esto posible solo con SQL? ¿O necesito seleccionar toda la tabla y luego buscar las filas en la memoria? Lo ideal sería evitar esto, si es posible, ya que la mesa puede ser bastante grande.

Respuestas:


78

En SQL Server 2005 y superior puede utilizar la función ROW_NUMBER . p.ej.

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

Vea el enlace en mi respuesta para obtener más detalles. stackoverflow.com/questions/1744802/…
Mike Atlas

ENTRE 51 y 60 - es inclusivo.
Drew Miller

1
Pero esto primero seleccionará todo y luego de esa selección tomará solo 10, ¿verdad? ¿O la primera consulta / vista ya tendrá solo 10?
Tadej

139

SQL Server 2012 y versiones posteriores han agregado esta sintaxis:

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

11
Tenga en cuenta que debe usar ORDER BY ___ para usar el comando OFFSET ... no es que deba intentar paginar sin una orden.
James Haug

También tenga en cuenta que la 'nueva' sintaxis extrañamente tiene una penalización de rendimiento lineal con @skip! El enfoque de número de fila NO tiene esto (solo probado en orden indexado). Sin embargo, para lo @Skip menos de 20, la nueva sintaxis es más rápida que el enfoque de número de fila.
Eske Rahn

22

LINQ to SQL hace esto usando una función de ventana ROW_NUMBER:

  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;

Esto funciona, pero la necesidad de fabricar el número de fila a partir de ORDER BY puede hacer que su consulta se ordene en el lado del servidor y cause problemas de rendimiento. Incluso cuando un índice puede satisfacer el requisito ORDER BY, la consulta aún debe contar 1000 filas antes de comenzar a devolver resultados. Con demasiada frecuencia, los desarrolladores olvidan esto y simplemente lanzan un control de paginación sobre una tabla de filas de 5 mil y se preguntan por qué la primera página se devuelve mucho más rápido que la última ...

No obstante, usar ROW_NUMBER () es probablemente el mejor equilibrio entre facilidad de uso y buen rendimiento, siempre que se asegure de evitar la ordenación (la condición ORDER BY puede satisfacerse mediante un índice).


1
Gracias por la información extra de rendimiento, tendrás que tener cuidado y probarlo.
Ray

Probado y para mi tabla de medio millón de filas, esa última página es aproximadamente 7 veces más lenta que la primera página. No es ideal, pero aceptable para mí.
Ray

6

Prueba este:

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

Ejemplo:

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

4

Hacer esto:

Ejecute .Skip (1000) .Tome (100) en un contexto de datos LINQ to SQL y observe la salida SQL. Generará una declaración SQL para usted que hace lo que está describiendo.

No será tan elegante, pero hace el trabajo.


2
No lo que se preguntaba.
RayLoveless

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.