¿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.