我正在使用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中实现相同的目标?
答案 0 :(得分:0)
您可以使用order by
,然后使用fetch
和offset
来获取行,如下所示:
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
。