我正在尝试实现一个稍微不同的分页例程。
为了一个简单的例子,我们假设我有一个表定义并填充如下:
DECLARE @Temp TABLE
(
ParentId INT,
[TimeStamp] DATETIME,
Value INT
);
INSERT INTO @Temp VALUES (1, '1/1/2013 00:00', 6);
INSERT INTO @Temp VALUES (1, '1/1/2013 01:00', 7);
INSERT INTO @Temp VALUES (1, '1/1/2013 02:00', 8);
INSERT INTO @Temp VALUES (2, '1/1/2013 00:00', 6);
INSERT INTO @Temp VALUES (2, '1/1/2013 01:00', 7);
INSERT INTO @Temp VALUES (2, '1/1/2013 02:00', 8);
INSERT INTO @Temp VALUES (3, '1/1/2013 00:00', 6);
INSERT INTO @Temp VALUES (3, '1/1/2013 01:00', 7);
INSERT INTO @Temp VALUES (3, '1/1/2013 02:00', 8);
TimeStamp
将始终是相同的间隔,例如每日数据,1小时数据,1分钟数据等。不会混合。
出于报告和演示目的,我想实现以下分页:
TimeStamp
订单pageSize
(例如4)开始,但会自动调整以包含与TimeStamp
匹配的其他记录。换句话说,如果一个ParentId
包含1/1/2013 01:00,则会覆盖建议的pageSize
,并且所有{{1}将包含小时01:00的所有记录}。它几乎就像ParentId's
选项。 因此,以TOP WITH TIES
为4运行此查询将返回6条记录。默认情况下,有3小时00:00和1小时pageSize
,但因为还有更多小时01:00
,所以会覆盖01:00's
以返回所有小时pageSize
和{ {1}}。
这是我到目前为止的内容,我认为我很接近,因为它适用于第一次迭代,但后续00:00
行的后续查询不起作用。
01:00
ROW_NUMBER确保满足最小pageSize,但RANK将包含额外的关系。
答案 0 :(得分:1)
declare @Temp as Table ( ParentId Int, [TimeStamp] DateTime, [Value] Int );
insert into @Temp ( ParentId, [TimeStamp], [Value] ) values
(1, '1/1/2013 00:00', 6),
(1, '1/1/2013 01:00', 7),
(1, '1/1/2013 02:00', 8),
(2, '1/1/2013 00:00', 6),
(2, '1/1/2013 01:00', 7),
(2, '1/1/2013 02:00', 8),
(3, '1/1/2013 00:00', 6),
(3, '1/1/2013 01:00', 7),
(3, '1/1/2013 02:00', 8);
declare @PageSize as Int = 4;
declare @Page as Int = 1;
with Alpha as (
select ParentId, [TimeStamp], Value,
Rank() over ( order by [TimeStamp] ) as Rnk,
Row_Number() over ( order by [TimeStamp] ) as RowNum
from @Temp ),
Beta as (
select Min( Rnk ) as MinRnk, Max( Rnk ) as MaxRnk
from Alpha
where ( @Page - 1 ) * @PageSize < RowNum and RowNum <= @Page * @PageSize )
select A.*
from Alpha as A inner join
Beta as B on B.MinRnk <= A.Rnk and A.Rnk <= B.MaxRnk
order by [TimeStamp], ParentId;
修改强>: 另一种查询,用于分配页码,以便在不重叠行的情况下实现下一页/上一页:
with Alpha as (
select ParentId, [TimeStamp], Value,
Rank() over ( order by [TimeStamp] ) as Rnk,
Row_Number() over ( order by [TimeStamp] ) as RowNum
from @Temp ),
Beta as (
select ParentId, [TimeStamp], Value, Rnk, RowNum, 1 as Page, 1 as PageRow
from Alpha
where RowNum = 1
union all
select A.ParentId, A.[TimeStamp], A.Value, A.Rnk, A.RowNum,
case when B.PageRow >= @PageSize and A.TimeStamp <> B.TimeStamp then B.Page + 1 else B.Page end,
case when B.PageRow >= @PageSize and A.TimeStamp <> B.TimeStamp then 1 else B.PageRow + 1 end
from Alpha as A inner join
Beta as B on B.RowNum + 1 = A.RowNum
)
select * from Beta
option ( MaxRecursion 0 )
请注意,递归CTE通常表现不佳。
答案 1 :(得分:0)
我认为您使用row_number()
和rank()
的策略过于复杂。
从数据中选择前4个时间戳。然后选择与之匹配的任何时间戳:
select *
from @temp
where [timestamp] in (select top 4 [timestamp] from @temp order by [TimeStamp])