Implemente a funcionalidade de paginação (ignorar / receber) com esta consulta

138

Eu tenho tentado entender um pouco sobre como implementar paginação personalizada no SQL, por exemplo, lendo artigos como este .

Eu tenho a seguinte consulta, que funciona perfeitamente. Mas eu gostaria de implementar a paginação com este.

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

O que é que eu quero

Tenho postagens no fórum, com entradas relacionadas. Desejo obter as postagens com as entradas adicionadas mais recentes, para que eu possa selecionar as postagens debatidas recentemente.

Agora, quero conseguir as "10 a 20 postagens ativas recentemente", em vez de "as 10 principais".

O que eu tentei

Eu tentei implementar as funções ROW como a do artigo, mas realmente sem sorte.

Alguma idéia de como implementá-lo?

Lars Holdgaard
fonte

Respostas:

288

No SQL Server 2012 , é muito, muito 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

Se queremos pular 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

(Prefiro marcar isso como um hack - mas é usado, por exemplo, pelo NHibernate. Para usar uma coluna escolhida com sabedoria, como ORDER BY é a maneira preferida)

para responder à pergunta:

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

Novas palavras-chave offsete fetch next(apenas seguindo os padrões SQL) foram introduzidas.

Mas acho que você não está usando o SQL Server 2012 , certo ? Na versão anterior, é um pouco (pouco) difícil. Aqui está uma comparação e exemplos para todas as versões do servidor SQL: aqui

Portanto, isso poderia funcionar no 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
fonte
Muito obrigado! Essa é uma resposta muito boa! Única pergunta sobre o sql 2008. Quero que o ORDER BY aconteça antes do WHERE, pois atualmente ele classifica o subconjunto, mas queremos selecionar algo de todo o conjunto ... Alguma idéia? :) Mais uma vez obrigado
Lars Holdgaard
2
Se eu entendi corretamente, você gostaria de classificar por LastDate, certo? então podemos alterar a cláusula OVER () desta maneira: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ). E remova a última ORDER BY PostId . Agora, o CTE deve ser classificado "mais cedo", conforme necessário. corrigir?
Radim Köhler
1
Obrigado, isso ajudou, uma observação sobre o exemplo de 2012, ordem é obrigatória, eu estava tentando isso sem ordem por cláusula e recebi o erro "sintaxe incorreta" não fazia ideia do que estava errado até eu procurar na sintaxe do MSDN e descobrir que a ordem é obrigatória .
Esen
A primeira linha é 1 ou 0? O WHERE WHERE RowNumber >= @Start AND RowNumber < @Enddeve obter as primeiras 1000 linhas se @Startfor 0 e @Endfor 1000?
precisa saber é o seguinte
1
Muito obrigado
Mafii
8

Para fazer isso no SQL Server, você deve solicitar a consulta por uma coluna, para poder especificar as linhas que deseja.

Exemplo:

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

E você não pode usar a palavra-chave "TOP" ao fazer isso.

Você pode saber mais aqui: https://technet.microsoft.com/pt-br/library/gg699618%28v=sql.110%29.aspx

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

use isso no final da sua sintaxe de seleção. =)

Nicolas Vinícius Sroczynski
fonte
5

SQL 2008

A resposta de Radim Köhler funciona, mas aqui está uma versão mais curta:

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

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

Tadej
fonte
-1

Você pode usar a consulta aninhada para paginação da seguinte maneira:

Paginação de 4 linhas para 8 linhas em que CustomerId é a chave primária .

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
fonte