2010-01-25 13 views
131

En PostgreSQL están las palabras clave Limit y Offset que permitirán una paginación muy fácil de los conjuntos de resultados.¿Equivalente a LIMIT y OFFSET para SQL Server?

¿Cuál es la sintaxis equivalente para Sql Server?

+0

Para SQL Server 2012, esta característica se implementa en forma fácil. Ver [mi respuesta] (http://stackoverflow.com/a/9261762/1045444) –

+0

Gracias por hacer esta pregunta, nos vemos obligados a pasar de MySQL a MsSQL :( – Logikos

Respuesta

112

El equivalente de LIMIT es SET ROWCOUNT, pero si quieres la paginación genérica que es mejor escribir una consulta como esta:

;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 

La ventaja en este caso es la parametrización del límite de offset y en caso de que decida cambiar sus opciones de búsqueda (o permiten que el usuario lo haga).

Nota: el parámetro debe utilizar la indexación basada en uno para esto en lugar de la indexación basada en cero normal.

+14

Antiguo ahora. Servidor Sql 2012 y posterior soporte OFFSET/FETCH –

+25

@JoelCoehoorn No es viejo. Me acaban de asignar a un proyecto usando SLQ Server 2008 habiendo usado solo mysql en el pasado ... – Cthulhu

+0

Esto es bastante bueno, pero debe ajustarse un poco 'WHERE RowNum> = (@Offset + 1) ' –

0

En el servidor SQL que usaría TOP junto con ROW_NUMBER()

7

Puede utilizar ROW_NUMBER en una expresión de tabla común para lograr esto.

;WITH My_CTE AS 
(
    SELECT 
      col1, 
      col2, 
      ROW_NUMBER() OVER(ORDER BY col1) AS row_number 
    FROM 
      My_Table 
    WHERE 
      <<<whatever>>> 
) 
SELECT 
    col1, 
    col2 
FROM 
    My_CTE 
WHERE 
    row_number BETWEEN @start_row AND @end_row 
+0

Esto debería haber sido la respuesta aceptada. Perfecto –

2

Otra muestra:

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; 
+13

Quité su discurso de odio anti-microsoft. No discutas las guerras santas aquí; solo responda y haga preguntas de una manera no subjetiva. – Earlz

2

Hay here alguien que le dice acerca de esta característica en SQL 2011, es triste que elijan un poco de la palabra llave "OFFSET/FETCH" pero no es standart que bien.

150

Esta característica ahora se hace fácil en el servidor sql 2012. Esto funciona pero el servidor sql 2012 en adelante. límite con desplazamiento para seleccionar 11 a 20 filas en SQL Server:

SELECT email FROM emailTable 
WHERE id=3 
ORDER BY Id 
OFFSET 10 ROWS 
FETCH NEXT 10 ROWS ONLY; 

// compensar - no. de filas omitidas

// siguiente: obligatorio no. de las filas siguientes

+4

¿Hay un equivalente de 'SQL_CALC_FOUND_ROWS' al usar esto? – Petah

+1

@Petah @@ Rowcount le dará que creo que –

+3

esta debería haber sido la respuesta correcta – Jeff

2

Añadiendo una ligera variación en la solución de Aaronaught, normalmente parametrizo el número de página (@PageNum) y el tamaño de página (@PageSize). De esta manera cada evento página, haga clic simplemente envía el número de página solicitada junto con un tamaño de página configurable:

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 
21
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} 

Una nota: Esta solución sólo funciona en SQL Server 2005 o superior, ya que esta fue cuando se implementó ROW_NUMBER().

+0

He estado usando esta consulta por un tiempo y funciona muy bien, así que gracias por eso. Me pregunto qué representa el 'xx'. – Urbley

+0

la consulta secundaria requiere un nombre. como no lo estoy usando, solo ponga xx allí – jorgeu

+1

El xx es solo un alias de tabla. Podría ser un poco más claro si dijera 'AS xx' –

2

El más cercano que pude hacer es

select * FROM(SELECT *, ROW_NUMBER() over (ORDER BY ID) as ct from [db].[dbo].[table]) sub where ct > fromNumber and ct <= toNumber 

Qué supongo similar a select * from [db].[dbo].[table] LIMIT 0, 10

+0

, funciona gracias. – oguzhan

0
select top (@TakeCount) * --FETCH NEXT 
from(
    Select ROW_NUMBER() OVER (order by StartDate) AS rowid,* 
    From YourTable 
)A 
where Rowid>@SkipCount --OFFSET 
1
@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 
1

Ya que nadie proporciona este código aún:

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

puntos importantes:

  • ORDER BY debe ser idéntica
  • @limit puede ser reemplazado con el número de resultados a recuperar,
  • @offset es el número de resultados para saltar
  • favor comparar el rendimiento con las soluciones anteriores, ya que pueden ser más eficiente
  • esta solución duplica las cláusulas where y order by, y proporcionará resultados incorrectos si no están sincronizadas
  • por el contrario order by está allí de forma explícita si eso es lo que se necesita
1

Para mí el uso de OFFSET y FETCH juntos fue lento, por lo que utiliza una combinación de TOP y el desplazamiento como éste (que era más rápido):

SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename 
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname 

Nota: Si utiliza TOP y compensar juntos en la misma consulta como:

SELECT TOP 20 columname1, columname2 FROM tablename 
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS 

Luego aparece un error, por lo tanto, para usar TOP y OFFSET juntos, debe separarlo con una subconsulta.

Y si es necesario utilizar SELECT DISTINCT continuación, la consulta es como:

SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2 
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname 

Nota: El uso de SELECT DISTINCT con ROW_NUMBER no funcionó para mí.

+0

obtengo "Un TOP no se puede usar en la misma consulta o sub consulta como un DESPLAZAMIENTO". – MichaelRushton

+0

Tiene razón @MichaelRushton, no puede usarse en la misma consulta o en la misma sub consulta, luego debe usar una subconsulta para separarla. Entonces, si tiene el SQL como 'SELECCIONE TOP 20 id FROM table1 donde id> 10 ordene por fecha OFFSET 20 rows', debe transformarlo como' SELECT TOP 20 * FROM (SELECCIONE id FROM table1 donde id> 10 ordene por fecha OFFSET 20 FILAS) t1'. Editaré mi respuesta. Gracias y discúlpeme por mi inglés. – sebasdev

1
-- @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 
Cuestiones relacionadas