Você não disse se estava planejando ajustar "X" e "Y" toda vez que fizer a paginação. Se você não fizer isso, a abordagem provavelmente só será válida se você tiver uma alta confiança de que os dados são bastante estáticos.
Considere o seguinte exemplo:
Minha tabela T tem 100 linhas de data e hora para "hoje", com ID=1 a 100 respectivamente, e eu quero as últimas 20 linhas para minha primeira página. Então eu faço isso:
select *
from T
where date_col = trunc(sysdate)
order by id desc
fetch first 20 rows only
Eu executo minha consulta e obtenho ID =100 para 80. Até agora tudo bem - está tudo na página do usuário, e eles levam 30 segundos minutos para ler os dados. Durante esse tempo, outros 17 registros foram adicionados à tabela (ID=101 a 117).
Agora o usuário pressiona "Próxima página"
Agora eu executo a consulta novamente para obter o próximo conjunto
select *
from T
where date_col = trunc(sysdate)
order by id desc
offset 20 fetch next 20 rows only
Eles não verão as linhas de 80 a 60, o que seria sua expectativa, porque os dados foram alterados. Eles iriam
a) obter as linhas ID=117 até 97 e ignorá-las devido ao OFFSETb) e depois obter as linhas ID=97 até 77 para serem exibidas na tela
Eles ficarão confusos porque estão vendo praticamente o mesmo conjunto de linhas que viram na primeira página.
Para paginação em relação a dados alterados, você geralmente deseja ficar longe da cláusula de compensação e usar seu aplicativo para anotar onde você chegou, ou seja,
Página 1
select *
from T
where date_col = trunc(sysdate)
order by id desc
fetch first 20 rows only
Eu busco ID=100 até 80...Eu tomo nota dos 80. Minha próxima consulta será então
select *
from T
where date_col = trunc(sysdate)
AND ID<80
order by id desc
fetch first 20 rows only
e minha próxima consulta seria
select *
from T
where date_col = trunc(sysdate)
AND ID<60
order by id desc
fetch first 20 rows only
e assim por diante.