Sybase偏移分页

时间:2011-10-13 19:07:21

标签: pagination sybase

有没有简单的方法在sybase中实现分页? 在postgres中有mysql的限制和偏移,有限制X,Y。那么sybase呢?有一个限制结果的顶级约束,但要实现完全分页,还需要抵消。 如果有几个pags,这不是问题,我可以简单地在客户端调整结果,但如果有数百万行,我只想获取我需要的数据。

7 个答案:

答案 0 :(得分:4)

// First row = 1000
// Last row = 1009
// Total row = 1009 - 1000 + 1 = 10
// Restriction: exec sp_dboption 'DATABASE_NAME','select into/bulkcopy','true'
select TOP 1009 *, rownum=identity(10) 
into #people
from people 
where upper(surname) like 'B%'
select * from #people where rownum >= 1000
drop table #people
// It shoulde be better SQL-ANSI-2008 (but we have to wait):
// SELECT * FROM people
// where upper(surname) like 'B%'
//    OFFSET 1000 ROWS FETCH NEXT 10 ROWS ONLY

答案 1 :(得分:3)

引自http://www.isug.com/Sybase_FAQ/ASE/section6.2.html#6.2.12

  

Sybase没有直接等同于Oracle的rownum,但在很多情况下可以模拟其功能。

您可以设置最大rowcount,这将限制任何特定查询返回的行数:

set rowcount 150

该限制将适用,直到重置:

set rowcount 0

您可以选择临时表,然后从中提取数据:

set rowcount 150

select pseudo_key = identity(3),
       col1,
       col2
  into #tempA
  from masterTable
 where clause...
 order by 2,3

select col1,col2 from #tempA where pseudo_key between 100 and 150

您可以通过仅存储ID列来优化临时表上的存储,然后将其连接回原始表以供选择。

常见问题解答还提出了其他解决方案,包括游标或Sybperl。

答案 2 :(得分:2)

我参加聚会很晚,但是我偶然发现了这个问题,并使用sybase doc中的TOP和START AT找到了更好的答案。您需要将ORDER BY用于,否则结果将无法预测。

http://dcx.sybase.com/1101/en/dbusage_en11/first-order-formatting.html

选择前2位开始于5 *    来自员工    按姓氏顺序排列;

答案 3 :(得分:0)

不幸的是,Sybase不提供设置启动和偏移限制的功能。您可以实现的最佳方法是使用SET ROWCOUNT来限制返回的记录数。如果您有1,000条记录并希望按50个条目分页,那么这样的内容将带回第一页......

set rowcount 50
select * from orders

第二页......

set rowcount 100
select * from orders

...然后您可以选择不在Java代码中显示前50个。显然,当您向前翻页时,您最终必须返回越来越大的数据集。关于如何处理1,000,000条记录的问题对于分页的用户界面似乎不实用。没有用户在Google上搜索,然后向前翻页1000次寻找内容。

如果我有自然钥匙怎么办?

如果您确实拥有相对较大的数据集,并且可以在数据上使用自然键,这将有助于限制返回的记录。例如,如果您有一个联系人列表,并且有一个界面允许您的用户选择A到Z来根据Surname对目录中的人进行寻呼,那么您可以执行以下操作...

set rowcount 50
select * from people 
where upper(surname) like 'B%'

如果有超过50个姓氏以'B'开头的人,请使用与上述相同的方法向前翻页......

set rowcount 100
select * from people 
where upper(surname) like 'B%'

...并删除Java代码中的前50个。

继续此示例之后,您可以按日期限制搜索,或者根据您的用户需求限制其他一些数据。

希望这有帮助!

答案 4 :(得分:0)

您可以尝试使用两次设置ROWCOUNT:

    declare @skipRows int, @getRows int
    SELECT @skipRows=50
    SELECT @getRows=10
    set ROWCOUNT @skipRows
    SELECT caslsource_id into #caslsource_paging FROM caslsources
    set rowcount @getRows
    Select * from caslsources where caslsource_id not in (select caslsource_id from #caslsource_paging)
    DROP TABLE #caslsource_paging

这会创建一个要跳过的临时行表。您需要将WHERE和ORER BY子句添加到两个SELECT中以跳过正确的页面。

答案 5 :(得分:0)

Sybase SQL Anywhere示例,每页行数:10,偏移量:1000。

SELECT top 10 start at 1001  * FROM employee order by employeeid

注意:您需要指定order by列。

答案 6 :(得分:0)

我不知道这是ASE还是其他产品,但是以下模式可在我使用过的多个数据库中运行,只要有一种方法可以以某种方式生成带有行号的临时表,并且您可以确定每行的唯一键:

输入参数:

declare @p_first int /* max number of rows to see; may be null (= all results); otherwise must be positive number */
declare @p_skipFirst int /* number of rows to skip before the results; must be nonnegative number */
declare @p_after PKTYPE /* key for the row before you start skipping; may be null */

给了一张桌子

RowNumber | RowIndex | DataCol1
1         | 1234     | Joe
2         | 1235     | Sue
3         | 2000     | John
4         | 2005     | Frank
5         | 3000     | Tom
6         | 4000     | Alice

参数集:

set @p_first = 5
set @p_skipFirst = 2
set @p_after = 1235

将代表第5行和第6行。

另外一组参数可以反向表示从表末尾的分页:

declare @p_last int /* max number of rows to see; may be null (= all results); otherwise must be positive number */
declare @p_skipLast int /* number of rows to skip after the results; must be nonnegative number */
declare @p_before PKTYPE /* key for the row after you start skipping; may be null */

假设未排序的表位于#resultsBeforeSort的索引列中,您可以使用以下脚本对此进行排序:

RowIndex

该脚本设置参数select RowNumber = identity(10), * into #results from #resultsBeforeSort /* you might also wish to have a where clause on this query this sort is dynamically generated based on a sort expression and ultimately ended with RowIndex to ensure a deterministic order */ order by Column1, Column2 desc, RowIndex declare @p_total int, @p_min int, @p_max int select @p_total = count(*) from #results select @p_min = case when @p_after is null then 1 + @p_skipFirst else @p_total + 1 end select @p_min = RowNumber + @p_skipFirst from #results where [RowIndex] = @p_after select @p_max = case when @p_before is null then @p_total - @p_skipLast else 0 end select @p_max = RowNumber - @p_skipLast from #results where [RowIndex] = @p_before declare @p_min2 int, @p_max2 int set @p_min2 = @p_min set @p_max2 = @p_max select @p_max2 = case when @p_first is null then @p_max else @p_min + @p_first - 1 end select @p_min2 = case when @p_last is null then @p_min else @p_max - @p_last end select @p_min = case when @p_min2 > @p_min then @p_min2 else @p_min end select @p_max = case when @p_max2 < @p_max then @p_max2 else @p_max end @p_min@p_max以及临时表@p_total

然后可以使用它来选择实际数据;选择2个表结果,第一个是元数据(之所以选择它,是因为第二个表可能没有任何实际行,并且您的阅读器实现可能无法处理而不回溯):

#results

紧随其后的是您实际想要的结果分页窗口:

select [Count] = @p_total, 
    HasPreviousPage = (case when @p_min > 1 then 1 else 0 end),
    HasNextPage = (case when @p_max + 1 < @p_total then 1 else 0 end)

执行此通用解决方案可以显示所需的任何分页策略。您可以通过select [RowIndex], Col1, Col2, Col3 from #results where RowNumber between @p_min and @p_max @p_after(或@p_first@p_before)进行流媒体解决方案(facebook,google,stackoverflow,reddit等)。您可以使用@p_last@p_first进行偏移+拍摄。您还可以使用相同的参数@p_skipFirst@p_first = size来进行页面+尺寸的设置。此外,您还可以使用其他参数组合来执行更多深奥的分页策略(最后X页,在绝对记录之间,偏移量+定位符之间)。


这就是说,Sybase(SAP)ASE现在确实通过@p_skipFirst = (page - 1) * size直接支持偏移+获取策略。如果您只希望支持该策略,则可以将以上内容简化为:

rows limit @p_first offset @p_skipFirst