Como selecionar apenas 1 linha do oracle sql?

110

Eu quero usar a sintaxe do oracle para selecionar apenas 1 linha da tabela DUAL. Por exemplo, desejo executar esta consulta:

SELECT user 
  FROM DUAL

... e teria, tipo, 40 registros. Mas preciso apenas de um registro. ... E, eu quero que isso aconteça sem uma WHEREcláusula.

Preciso de algo no campo table_name, como:

SELECT FirstRow(user) 
  FROM DUAL
Ben
fonte
1
Qual versão do Oracle? Usar ROWNUM ou ROW_NUMBER (9i +) significaria a necessidade de uma cláusula WHERE
Pôneis OMG
1
Você nomeou uma mesa dual?
ypercubeᵀᴹ
1
@ypercube dualé a tabela do sistema no oracle
4
@Ben, você realmente não deveria criar uma tabela chamada DUAL. É um pouco como #define TRUE 0em C - claro, pode funcionar para você, mas os futuros desenvolvedores irão odiar você.
Jeffrey Kemp
3
Você realmente tentou correr select user from dual? Se não, tente fazer isso e veja o que você ganha. Em um sistema oracle padrão, você receberá de volta o usuário com o qual está executando o comando.
Shannon Severance

Respostas:

169

Você usa ROWNUM.

ie.

SELECT user FROM Dual WHERE ROWNUM = 1

http://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns009.htm

vírus da mente
fonte
@ypercube, pelo que posso dizer, sim. (Pelo menos funciona para minha instalação do oracle10g.)
@bdares: vai funcionar, sim. Mas não sua resposta, com o order by.
ypercubeᵀᴹ
1
Sim. ROWNUM é uma coluna especial que é adicionada ao conjunto de resultados enumerando os resultados. Você também pode usá-lo para selecionar vários, por exemplo, se quiser encontrar os 10 funcionários mais bem pagos, pode dizer "SELECIONE usuário DE funcionários ONDE ROWNUM <= 10 ORDEM POR
DESCIDA
10
@mkdess: Não, ORDER BYé aplicado após o WHERE.
ypercubeᵀᴹ
15
Você precisaria de:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ
49

Encontrei essa "solução" escondida em um dos comentários. Já que estava pesquisando por um tempo, gostaria de destacar um pouco (ainda não posso comentar ou fazer esse tipo de coisa ...), então usei assim:

SELECT * FROM (SELECT [Column] FROM [Table] ORDER BY [Date] DESC) WHERE ROWNUM = 1

Isso me imprimirá a entrada [Coluna] desejada da entrada mais recente na tabela, supondo que [Data] seja sempre inserida via SYSDATE.


fonte
Descobri que também funcionará se você solicitar por ROWID, desde que você nunca exclua nenhum registro e sempre se preocupe com o último inserido / modificado.
vapcguy
@vapcguy: Não espere que o ROWID seja ordenado, mesmo que você nunca apague uma linha da tabela! Mesmo que funcione para você agora, nunca é garantido que funcione em versões futuras.
D. Mika
@ D.Mika Na verdade, se funcionar agora, e você nunca adicionar / remover / atualizar / excluir registros, nunca deverá haver problemas. Os registros só podem ser alterados se você realmente os alterar. Existe esse equívoco que de alguma forma ROWIDé modificado aleatoriamente pelo Oracle. Não é. Baseia-se na modificação real das linhas, ou seja, você exclui uma e depois insere outra. O inserido obterá o antigo ROWID. Existem coisas como tabelas estáticas que nunca são atualizadas - como os estados nos Estados Unidos são um bom exemplo - onde, se mudasse, provavelmente teria outras repercussões, de qualquer maneira, quando isso é bom.
vapcguy
@vapcguy: Bem, isso é quase certo. Mas existem outras operações que irão alterar o ROWID. E se você exportar / importar a tabela por algum motivo? Há outras operações, mas algumas precisam ATIVAR O MOVIMENTO DA LINHA. Só quero dizer que não é uma boa ideia confiar em um detalhe de implementação que pode mudar no futuro.
D. Mika
@ D.Mika Tenho certeza de que se houver alguma operação em que o ROWIDpossa ser alterado, um bom DBA iria procurá-la e fazer o que pudesse para evitá-la se houvesse a possibilidade de estarem afetando uma tabela estática, como descrevi. apenas o aplicativo deve estar operando. Uma exportação de tabela pode ser feita com uma SELECTinstrução, em vez disso. A importação aconteceria uma vez e nunca mais. Entendi, é definitivamente necessário cuidado, mas os problemas estão longe de ser inevitáveis.
vapcguy
35

Esta sintaxe está disponível no Oracle 12c:

select * from some_table fetch first 1 row only;
select * from some_table fetch first 1 rows only;
select * from some_table fetch first 10 row only;
select * from some_table fetch first 10 rows only;

^^ Eu só queria demonstrar que tanto a linha quanto as linhas (plural) podem ser usadas independentemente da pluralidade do número de linhas desejado.)

mancini0
fonte
1
select * from some_table busca a primeira linha apenas; não está funcionando no meu devloper swl nem no sql mais, portanto, erro ao buscar.
nikhil sugandh
Você está usando o oracle 12c?
mancini0
eu realmente não sei, mas quando eu o abro mostra assim: SQL * PLus versão 10.1.0.4.2 não é 12 c
nikhil sugandh
correto - provavelmente você está usando a versão 10.1.xxx, pode SELECIONAR * DA VERSÃO V $
mancini0
10

temos 3 opções para obter a primeira linha na tabela Oracle DB.

1) select * from table_name where rownum= 1é a melhor maneira

2) select * from table_name where id = ( select min(id) from table_name)

3)

select * from 
    (select * from table_name order by id)
where rownum = 1
Deva
fonte
Obrigado pelas respostas: no ponto 3) "nowrum = 1" provavelmente deve ser alterado para "rownum = 1".
Andre Nel
7

Pelo que eu sei, a dualtabela no Oracle é uma tabela especial com apenas uma linha. Então, isso seria suficiente:

SELECT user
FROM dual
ypercubeᵀᴹ
fonte
isso não é verdade, selecione o usuário da dupla deve fornecer todos os usuários
Ben
O mesmo acontece com a Wikipediaa bout dual in Oracle
ypercubeᵀᴹ
1
.. e acabei de experimentar no meu sistema, funciona como ypercube e todas as menções de documentação relacionadas. @ Ben
Sathyajith Bhat
1
@Ben dual não é uma visualização de catálogo, não mostrará "todos os usuários". Você usaria uma visão como ALL_USERS para esse propósito.
março
7

👌 A resposta é:

Você deve usar a consulta aninhada como:

SELECT *
FROM ANY_TABLE_X 
WHERE ANY_COLUMN_X = (SELECT MAX(ANY_COLUMN_X) FROM ANY_TABLE_X) 

=> Em PL / SQL "ROWNUM = 1" NÃO é igual a "TOP 1" de TSQL.

Portanto, você não pode usar uma consulta como esta: "select * from any_table_x where rownum = 1 order by any_column_x;" Como o oracle obtém a primeira linha, aplica ordem por cláusula.

Fuat
fonte
1
Adicione alguns esclarecimentos à sua resposta
hgwhittle
A sintaxe incomum deve ser evitada sem um bom motivo. Nesse caso, seria útil fornecer um caso de teste ou um número de bug. Lembro-me vagamente de alguns problemas estranhos com rownum = 1, mas não devemos permitir que bugs antigos afetem nosso código mais.
Jon Heller
7
@hgwhittle, A razão pela qual Fuat está correto é porque ROWNUM não se preocupa com 'ordenar por', ele apenas pega o primeiro registro que pode encontrar e o retorna imediatamente. Em outras palavras, o qualificador ROWNUM não respeita o comando "Ordenar por". Eu gostaria que não fosse o caso, mas Fuat está correto, para usar a consulta aninhada.
Eric Milliot-Martinez de
5

Não há limit 1condição (isso é MySQL / PostgresSQL) no Oracle, você precisa especificar where rownum = 1.

Oh Chin Boon
fonte
5

"FirstRow" é uma restrição e, portanto, é colocada na wherecláusula e não na selectcláusula. E é chamado de rownum

select * from dual where rownum = 1;
gdoron está apoiando Monica
fonte
1
Observe que isso não funcionará conforme o esperado em combinação com ORDER BY, já que o pedido só acontece após a cláusula where. Em outras palavras, para obter o topo de uma determinada consulta classificada, o rownum é totalmente inútil.
Nyerguds
@Nyerguds, isso é apenas meia verdade. Você pode usar order by before Wherecom uma consulta de visualização.
gdoron está apoiando Monica de
4
O quê, então SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Bem, isso pode funcionar, mas parece muito idiota, tbh.
Nyerguds
2

Se qualquer linha servir, tente:

select max(user)  
from table;

Nenhuma cláusula where.

Raihan
fonte
9
Certamente levará apenas alguns segundos para você experimentar por si mesmo
Matt Donnan
1
select name, price
  from (
    select name, price, 
    row_number() over (order by price) r
      from items
  )
where r between 1 and 5; 
Andrew
fonte
1

select a.user from (select user from users order by user) a where rownum = 1

terá o melhor desempenho, outra opção é:

select a.user 
from ( 
select user, 
row_number() over (order by user) user_rank, 
row_number() over (partition by dept order by user) user_dept_rank 
from users 
) a 
where a.user_rank = 1 or user_dept_rank = 2

em cenários em que você deseja subconjuntos diferentes, mas acho que você também pode usar RANK()Mas, também gosto, row_number() over(...)pois nenhum agrupamento é necessário.

Tyler
fonte
0

Se você deseja recuperar apenas a primeira linha de um resultado classificado com o mínimo de subconsultas, tente o seguinte:

select *
  from ( select a.*
              , row_number() over ( order by sysdate_col desc ) as row_num
           from table_name a )
  where row_num = 1;
Jody Fedor
fonte
Onde sysdate_col seria o nome de qualquer coluna pela qual você deseja classificar e, claro, table_name seria o nome da tabela da qual você deseja que os dados classificados venham.
Jody Fedor
-1

Mais flexível do que select max()é:

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
Convidado
fonte