使用组合键的键集分页

时间:2019-08-15 02:41:36

标签: sql oracle pagination

我正在使用oracle 12c数据库,并且具有具有以下结构的表:

Id       NUMBER
SeqNo    NUMBER
Val      NUMBER
Valid    VARCHAR2

使用字段Id和SeqNo创建复合主键。

我想使用Valid ='Y'来获取数据,并应用页面大小为3的ketset分页。假设我有以下数据:

Id    SeqNo    Val    Valid
1     1        10     Y
1     2        20     N
1     3        30     Y
1     4        40     Y
1     5        50     Y
2     1        100    Y
2     2        200    Y

预期结果:

----------------------------
Page 1
----------------------------
Id    SeqNo    Val    Valid
1     1        10     Y
1     3        30     Y
1     4        40     Y
----------------------------
Page 2
----------------------------
Id    SeqNo    Val    Valid
1     5        50     Y
2     1        100    Y
2     2        200    Y

偏移分页可以这样进行:

SELECT * FROM table ORDER BY Id, SeqNo OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY;

但是,在实际的数据库中,它具有超过500万条记录,并且使用OFFSET将大大减慢查询速度。因此,我正在寻找一种ketset分页方法(使用一些唯一字段而非OFFSET跳过记录)

由于使用了复合主键,因此我需要使用来自多个字段的信息来偏移页面。

这是一个应在PostgreSQL中运行的示例SQL(获取第二页):

SELECT * FROM table WHERE (Id, SeqNo) > (1, 4) AND Valid = 'Y' ORDER BY Id, SeqNo LIMIT 3;

我如何在oracle中实现相同的目标?

2 个答案:

答案 0 :(得分:0)

您可以使用order by,然后使用fetchoffset来获取行,如下所示:

Select ID, SEQ, VAL, VALID FROM TABLE
WHERE VALID = 'Y'
ORDER BY ID, SEQ 
--FETCH FIRST 3 ROWS ONLY -- first page
--OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY -- second pages
--OFFSET 6 ROWS FETCH NEXT 3 ROWS ONLY -- third page

-更新-

您可以按以下方式使用row_number分析函数。

Select id, seqNo, Val, valid from
(Select t.*, 
Row_number(order by id, seq) as rn from table t
Where valid = 'Y')
Where ceil(rn/3) = 2 -- for page no. 2

干杯!

答案 1 :(得分:0)

row_number()分析函数与ceil算术函数一起使用。算术函数不会对性能产生负面影响,并且row_number() over (order by ...)表达式会自动对数据进行排序,而无需考虑插入顺序,也无需为主查询添加额外的order by子句。因此,请考虑:

select Id,SeqNo,
       ceil(row_number() over (order by Id,SeqNo)/3) as page
  from tab
 where Valid = 'Y';

P.S。它也适用于Oracle 11g,而OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY仅适用于Oracle 12c

Demo