Implemente la funcionalidad de paginación (omisión / toma) con esta consulta

138

He estado tratando de entender un poco sobre cómo implementar la paginación personalizada en SQL, por ejemplo, leyendo artículos como este .

Tengo la siguiente consulta, que funciona perfectamente. Pero me gustaría implementar paginación con este.

SELECT TOP x PostId FROM ( SELECT PostId, MAX (Datemade) as LastDate
 from dbForumEntry 
 group by PostId ) SubQueryAlias
 order by LastDate desc

Que es lo que quiero

Tengo publicaciones en el foro, con entradas relacionadas. Quiero obtener las publicaciones con las últimas entradas agregadas, para poder seleccionar las publicaciones recientemente debatidas.

Ahora, quiero poder obtener las "10 principales a 20 publicaciones recientemente activas", en lugar de las "10 principales".

Que he probado

He intentado implementar las funciones ROW como las del artículo, pero realmente sin suerte.

¿Alguna idea de cómo implementarlo?

Lars Holdgaard
fuente

Respuestas:

288

En SQL Server 2012 es muy muy fácil

SELECT col1, col2, ...
 FROM ...
 WHERE ... 
 ORDER BY -- this is a MUST there must be ORDER BY statement
-- the paging comes here
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

Si queremos omitir ORDER BY podemos usar

SELECT col1, col2, ...
  ...
 ORDER BY CURRENT_TIMESTAMP
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

(Prefiero marcar eso como un truco, pero se usa, por ejemplo, por NHibernate. Para usar una columna cuidadosamente seleccionada como ORDER BY es la forma preferida)

para responder la pregunta:

--SQL SERVER 2012
SELECT PostId FROM 
        ( SELECT PostId, MAX (Datemade) as LastDate
            from dbForumEntry 
            group by PostId 
        ) SubQueryAlias
 order by LastDate desc
OFFSET 10 ROWS -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

Se introdujeron nuevas palabras clave offsety fetch next(solo siguiendo los estándares SQL).

Pero supongo que no estás usando SQL Server 2012 , ¿ verdad ? En la versión anterior es un poco (poco) difícil. Aquí hay una comparación y ejemplos para todas las versiones del servidor SQL: aquí

Entonces, esto podría funcionar en SQL Server 2008 :

-- SQL SERVER 2008
DECLARE @Start INT
DECLARE @End INT
SELECT @Start = 10,@End = 20;


;WITH PostCTE AS 
 ( SELECT PostId, MAX (Datemade) as LastDate
   ,ROW_NUMBER() OVER (ORDER BY PostId) AS RowNumber
   from dbForumEntry 
   group by PostId 
 )
SELECT PostId, LastDate
FROM PostCTE
WHERE RowNumber > @Start AND RowNumber <= @End
ORDER BY PostId
Radim Köhler
fuente
¡Muchas gracias! Esa es una muy buena respuesta! Solo pregunta sobre el sql 2008. Quiero que ORDER BY suceda antes de WHERE, ya que actualmente ordenará el subconjunto, pero queremos seleccionar algo de todo el conjunto ... ¿Alguna idea? :) Una vez más, gracias
Lars Holdgaard
2
Si te entiendo correctamente, te gustaría ordenar por LastDate, ¿verdad? entonces podemos cambiar la cláusula OVER () de esta manera: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ). Y elimine el último ORDEN POR PostId . Ahora el CTE debe clasificarse 'antes' según sea necesario. ¿correcto?
Radim Köhler el
1
Gracias, esto ayudó, una nota sobre la muestra de 2012, ordenar por es obligatorio, estaba intentando esto sin ordenar por cláusula y recibí el error "sintaxis incorrecta" no tenía idea de lo que estaba mal hasta que examiné la sintaxis de MSDN y aprendí que ordenar por es obligatorio .
Esen
¿Es la primera fila 1 o 0? ¿Debería el DÓNDE WHERE RowNumber >= @Start AND RowNumber < @Endobtener las primeras 1000 filas si @Startes 0 y @Endes 1000?
CWSpear
1
Muchas gracias
Mafii
8

Para hacer esto en SQL Server, debe ordenar la consulta por una columna, para que pueda especificar las filas que desee.

Ejemplo:

select * from table order by [some_column] 
offset 10 rows
FETCH NEXT 10 rows only

Y no puede usar la palabra clave "TOP" al hacer esto.

Puede obtener más información aquí: https://technet.microsoft.com/pt-br/library/gg699618%28v=sql.110%29.aspx

Felipe VR
fuente
5
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

use esto al final de su sintaxis de selección. =)

Nicolas Vinícius Sroczynski
fuente
5

SQL 2008

La respuesta de Radim Köhler funciona, pero aquí hay una versión más corta:

select top 20 * from
(
select *,
ROW_NUMBER() OVER (ORDER BY columnid) AS ROW_NUM
from tablename
) x
where ROW_NUM>10

Fuente: https://forums.asp.net/post/4033909.aspx

Tadej
fuente
-1

Puede usar la consulta anidada para paginación de la siguiente manera:

Paginación de 4 filas a 8 filas donde CustomerId es la clave principal .

SELECT Top 5 * FROM Customers
WHERE Country='Germany' AND CustomerId Not in (SELECT Top 3 CustomerID FROM Customers
WHERE Country='Germany' order by city) 
order by city;
amoljdv06
fuente