T-SQL: пейджинг со связями
я пытаюсь реализовать процедуру подкачки, которая немного отличается.
для упрощения примера, предположим, что у меня есть таблица, определенная и заполняется следующим образом:
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
. Другими словами, если 1/1/2013 01:00 для одногоParentId
, предложилpageSize
будет переопределен, и все записи за час 01: 00 будут включены для всехParentId's
. Это почти как .
Итак, запуск этого запроса с pageSize
из 4 вернет 6 записей. Есть 3 часа 00:00 и 1 час 01:00
по умолчанию, но потому, что есть больше часа 01:00's
, the pageSize
было бы переопределено, чтобы вернуться весь час 00:00
и 01:00
.
вот что у меня есть до сих пор, и я думаю, что я близок, как это работает для первой итерации, но последовательные запросы для следующего pageSize+
строки не работают.
WITH CTE AS
(
SELECT ParentId, [TimeStamp], Value,
RANK() OVER(ORDER BY [TimeStamp]) AS rnk,
ROW_NUMBER() OVER(ORDER BY [TimeStamp]) AS rownum
FROM @Temp
)
SELECT *
FROM CTE
WHERE (rownum BETWEEN 1 AND 4) OR (rnk BETWEEN 1 AND 4)
ORDER BY TimeStamp, ParentId
ROW_NUMBER обеспечивает минимальный размер страницы, но ранг будет включать дополнительные связи.
2 ответов
Я думаю, что ваша стратегия использования row_number()
и rank()
это усложнять вещи.
просто выберите верхние 4 метки времени из данных. Затем выберите любые метки времени, соответствующие этим:
select *
from @temp
where [timestamp] in (select top 4 [timestamp] from @temp order by [TimeStamp])
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 )
обратите внимание, что рекурсивные CTEs часто масштабируются плохо.