Existe uma maneira de fazer uma consulta "Oracle" comportar-se como se ela contivesse uma cláusula "MySQL limit"?
No MySQL
, eu posso fazer isso:
select *
from sometable
order by name
limit 20,10
para conseguir a 21ª a 30ª filas (saltar as primeiras 20, dar as próximas 10). As linhas são selecionadas após o ordem por
, então realmente começa no 20º nome em ordem alfabética.
Em Oracle
, a única coisa que as pessoas mencionam é a pseudo-coluna rownum
, mas ela é avaliada antes ordenada por
, o que significa isto:
select *
from sometable
where rownum <= 10
order by name
irá devolver um conjunto aleatório de dez filas ordenadas pelo nome, que normalmente não é o que eu quero. Ele também não permite'não permite especificar um offset.
Você pode usar uma subconsulta para isso, como
select *
from
( select *
from emp
order by sal desc )
where ROWNUM <= 5;
Veja também o tópico Sobre ROWNUM e resultados limitantes no Oracle/AskTom para mais informações.
*Atualização***: Para limitar o resultado com os limites inferior e superior, as coisas ficam um pouco mais inchadas com
select * from
( select a.*, ROWNUM rnum from
( <your_query_goes_here, with order by> ) a
where ROWNUM <= :MAX_ROW_TO_FETCH )
where rnum >= :MIN_ROW_TO_FETCH;
(Copiado do artigo AskTom especificado)
**Atualização 2***: Começando com Oracle 12c (12.1) há uma sintaxe disponível para limitar as linhas ou começar em offsets.
SELECT *
FROM sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
Veja esta resposta para mais exemplos. Obrigado a Krumia pela dica.
Uma solução analítica com apenas uma consulta aninhada:
SELECT * FROM
(
SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
)
WHERE MyRow BETWEEN 10 AND 20;
Rank()
pode ser substituído por Row_Number()
mas pode retornar mais registros do que você está esperando se houver valores duplicados para o nome.
(não testado) algo como isto pode fazer o trabalho
WITH
base AS
(
select * -- get the table
from sometable
order by name -- in the desired order
),
twenty AS
(
select * -- get the first 30 rows
from base
where rownum < 30
order by name -- in the desired order
)
select * -- then get rows 21 .. 30
from twenty
where rownum > 20
order by name -- in the desired order
Há também a classificação da função analítica, que você pode usar para fazer pedidos.