Sql 最好的分页方式
Sql best way to pagination
我有#temp table,我需要对 table 中的所有数据进行分页。 table 分页的最佳方法是什么?
create table #temp (
Id int
,SomeName nvarchar(100)
)
create table #tempPage (
Id int
,SomeName nvarchar(100)
,PageIndex int
)
--Test data
insert #temp (Id, SomeName) values
(1,'A'),
(2,'B'),
(3,'C'),
(4,'D'),
(5,'F'),
(6,'G'),
(7,'H'),
(8,'A1'),
(9,'B1'),
(10,'C1'),
(11,'D1'),
(12,'F1'),
(13,'G1'),
(14,'H1');
--Page size
declare @PageSize int = 5
--Max page count
declare @MaxPages float = (
select
case when count(Id)%@PageSize>0 then count(Id)/@PageSize+1 else count(Id)/@PageSize end
from #temp
)
declare @PageFrom int = 0
declare @CurrentPage int = 1
while @CurrentPage <= @MaxPages
begin
insert #tempPage (Id, SomeName, PageIndex)
SELECT
Id, SomeName, @CurrentPage
FROM #temp
ORDER BY id OFFSET @PageFrom ROWS
FETCH NEXT @PageSize ROWS ONLY;
set @PageFrom = @PageFrom + @PageSize
set @CurrentPage = @CurrentPage + 1
end
select * from #tempPage
drop table #temp
drop table #tempPage
结果:
大数据处理速度很慢。我用的是Sql 2012
女士
基于集合的操作性能更好。避免逐行处理。
我们可以使用数据库分配的row_number除以每页我们想要的记录数来生成页面索引。如果我们截断/(四舍五入并消除小数点),我们将获得所需的页面索引。
类似于:
SELECT ID
, SomeName
, round(ROW_NUMBER() OVER(ORDER BY SomeName ASC)/5,0,1) AS PageIndex
FROM #temp
ORDER BY PageIndex, SomeName
- 5 表示每“页”的记录数
- 0 因为我们不关心小数,但我们不希望在截断小数之前发生舍入。
- 1 截断为 0 位小数 w/o 四舍五入。
我假设您知道可以将其包装在 CTE 中并添加一个 where 子句以获得所需的特定页面
由于您正在寻找最佳的分页方法,并且您正确地说您的解决方案对于大量数据来说速度很慢,因此您必须根据用户请求一次获取一页数据。
当用户点击第 2 页时,您将获得第 2 页的记录,而不是全部。
这里是示例代码
declare @PageNumber int = 2; -- just an example, will come from parameter
declare @PageTo int = @PageSize * @PageNumber;
declare @PageFrom int = @PageTo - @PageSize;
SELECT
Id, SomeName, @PageNumber
FROM #temp
WHERE Id > @PageFrom AND Id <= @PageTo
drop table #temp
您可以使用 OFFSET & FETCH NEXT 功能,
OFFSET 关键字只从 row_number 带来,而 FETCH NEXT 带来直到。
例如:
USE AdventureWorks2008R2
GO
SELECT
BusinessEntityID
,PersonType
,FirstName + ' ' + MiddleName + ' ' + LastName
FROM Person.Person
ORDER BY BusinessEntityID ASC
OFFSET 100 ROWS
FETCH NEXT 5 ROWS ONLY
GO
这样就可以利用参数进行分页,例如:
SELECT
BusinessEntityID
,PersonType
,FirstName + ' ' + MiddleName + ' ' + LastName
FROM Person.Person
ORDER BY BusinessEntityID
OFFSET (@PageNo - 1) * @RowCountPerPage ROWS
FETCH NEXT @RowCountPerPage ROWS ONLY
GO
为了更深入的理解和性能,您可以阅读this - Pagination with OFFSET / FETCH : A better way文章
我有#temp table,我需要对 table 中的所有数据进行分页。 table 分页的最佳方法是什么?
create table #temp (
Id int
,SomeName nvarchar(100)
)
create table #tempPage (
Id int
,SomeName nvarchar(100)
,PageIndex int
)
--Test data
insert #temp (Id, SomeName) values
(1,'A'),
(2,'B'),
(3,'C'),
(4,'D'),
(5,'F'),
(6,'G'),
(7,'H'),
(8,'A1'),
(9,'B1'),
(10,'C1'),
(11,'D1'),
(12,'F1'),
(13,'G1'),
(14,'H1');
--Page size
declare @PageSize int = 5
--Max page count
declare @MaxPages float = (
select
case when count(Id)%@PageSize>0 then count(Id)/@PageSize+1 else count(Id)/@PageSize end
from #temp
)
declare @PageFrom int = 0
declare @CurrentPage int = 1
while @CurrentPage <= @MaxPages
begin
insert #tempPage (Id, SomeName, PageIndex)
SELECT
Id, SomeName, @CurrentPage
FROM #temp
ORDER BY id OFFSET @PageFrom ROWS
FETCH NEXT @PageSize ROWS ONLY;
set @PageFrom = @PageFrom + @PageSize
set @CurrentPage = @CurrentPage + 1
end
select * from #tempPage
drop table #temp
drop table #tempPage
结果:
大数据处理速度很慢。我用的是Sql 2012
女士基于集合的操作性能更好。避免逐行处理。
我们可以使用数据库分配的row_number除以每页我们想要的记录数来生成页面索引。如果我们截断/(四舍五入并消除小数点),我们将获得所需的页面索引。
类似于:
SELECT ID
, SomeName
, round(ROW_NUMBER() OVER(ORDER BY SomeName ASC)/5,0,1) AS PageIndex
FROM #temp
ORDER BY PageIndex, SomeName
- 5 表示每“页”的记录数
- 0 因为我们不关心小数,但我们不希望在截断小数之前发生舍入。
- 1 截断为 0 位小数 w/o 四舍五入。
我假设您知道可以将其包装在 CTE 中并添加一个 where 子句以获得所需的特定页面
由于您正在寻找最佳的分页方法,并且您正确地说您的解决方案对于大量数据来说速度很慢,因此您必须根据用户请求一次获取一页数据。
当用户点击第 2 页时,您将获得第 2 页的记录,而不是全部。
这里是示例代码
declare @PageNumber int = 2; -- just an example, will come from parameter
declare @PageTo int = @PageSize * @PageNumber;
declare @PageFrom int = @PageTo - @PageSize;
SELECT
Id, SomeName, @PageNumber
FROM #temp
WHERE Id > @PageFrom AND Id <= @PageTo
drop table #temp
您可以使用 OFFSET & FETCH NEXT 功能, OFFSET 关键字只从 row_number 带来,而 FETCH NEXT 带来直到。 例如:
USE AdventureWorks2008R2
GO
SELECT
BusinessEntityID
,PersonType
,FirstName + ' ' + MiddleName + ' ' + LastName
FROM Person.Person
ORDER BY BusinessEntityID ASC
OFFSET 100 ROWS
FETCH NEXT 5 ROWS ONLY
GO
这样就可以利用参数进行分页,例如:
SELECT
BusinessEntityID
,PersonType
,FirstName + ' ' + MiddleName + ' ' + LastName
FROM Person.Person
ORDER BY BusinessEntityID
OFFSET (@PageNo - 1) * @RowCountPerPage ROWS
FETCH NEXT @RowCountPerPage ROWS ONLY
GO
为了更深入的理解和性能,您可以阅读this - Pagination with OFFSET / FETCH : A better way文章