Comment sélectionner seulement 1 ligne d'Oracle SQL?

111

Je veux utiliser la syntaxe oracle pour sélectionner seulement 1 ligne de la table DUAL. Par exemple, je souhaite exécuter cette requête:

SELECT user 
  FROM DUAL

... et il aurait, comme, 40 disques. Mais je n'ai besoin que d'un seul enregistrement. ... ET, je veux y arriver sans WHEREclause.

J'ai besoin de quelque chose dans le champ table_name tel que:

SELECT FirstRow(user) 
  FROM DUAL
Ben
la source
1
Quelle version d'Oracle? Utiliser ROWNUM ou ROW_NUMBER (9i +) signifierait avoir besoin d'une clause WHERE
OMG Ponies
1
Avez-vous nommé une table dual?
ypercubeᵀᴹ
1
@ypercube dualest la table système dans oracle
4
@Ben, vous ne devriez vraiment pas créer une table appelée DUAL. C'est un peu comme #define TRUE 0en C - bien sûr, cela pourrait fonctionner pour vous, mais les futurs développeurs vous détesteront.
Jeffrey Kemp
3
Avez-vous réellement essayé de courir select user from dual? Sinon, essayez-le et voyez ce que vous obtenez. Sur un système oracle standard, vous récupérerez l'utilisateur avec lequel vous exécutez la commande.
Shannon Severance

Réponses:

170

Vous utilisez ROWNUM.

c'est à dire.

SELECT user FROM Dual WHERE ROWNUM = 1

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

virus de l'esprit
la source
@ypercube autant que je sache, c'est le cas. (Au moins, cela fonctionne pour mon installation d'oracle10g.)
@bdares: cela fonctionnera, oui. Mais pas votre réponse, avec le order by.
ypercubeᵀᴹ
1
Oui. ROWNUM est une colonne spéciale qui est ajoutée à l'ensemble de résultats en énumérant les résultats. Vous pouvez également l'utiliser pour en sélectionner plusieurs, par exemple, si vous souhaitez trouver les 10 employés les mieux payés, vous pouvez dire "SELECT user FROM Employees WHERE ROWNUM <= 10 ORDER BY SALARY DESCENDING"
mindvirus
10
@mkdess: Non, ORDER BYest appliqué après le WHERE.
ypercubeᵀᴹ
15
Vous auriez besoin de:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ
49

J'ai trouvé cette "solution" cachée dans l'un des commentaires. Comme je le recherchais depuis un moment, j'aimerais le souligner un peu (je ne peux pas encore commenter ou faire de telles choses ...), voici donc ce que j'ai utilisé:

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

Cela m'imprimera l'entrée [Colonne] souhaitée à partir de l'entrée la plus récente de la table, en supposant que [Date] est toujours insérée via SYSDATE.


la source
J'ai trouvé que cela fonctionnera également si vous commandez par ROWID, tant que vous ne supprimez aucun enregistrement et que vous vous souciez toujours du dernier inséré / modifié.
vapcguy
@vapcguy: Ne vous attendez pas à ce que ROWID soit commandé, même si vous ne supprimez jamais une ligne du tableau! Même si cela fonctionne pour vous maintenant, il n'est jamais garanti de fonctionner dans les versions futures.
D.Mika
@ D.Mika En fait, si cela fonctionne maintenant, et que vous n'ajoutez jamais / supprimez / mettez à jour / supprimez des enregistrements, il ne devrait jamais y avoir de problèmes. Les enregistrements ne peuvent être modifiés que si vous les modifiez réellement. Il y a cette idée fausse selon laquelle il ROWIDest en quelque sorte modifié au hasard par Oracle. Ça ne l'est pas. Il est basé sur la modification effective des lignes, c'est-à-dire que vous en supprimez une, puis en insérez une. Celui inséré obtiendra l'ancien ROWID. Il y a des choses telles que les tables statiques qui ne sont jamais mises à jour comme des états aux États-Unis est un bon exemple, où si cela changeait, cela aurait probablement d'autres répercussions, de toute façon, quand c'est bien.
vapcguy
@vapcguy: Eh bien, c'est presque vrai. Mais il existe d'autres opérations qui changeront le ROWID. Que faire si vous exportez / importez la table pour une raison quelconque? Il existe d'autres opérations, mais certaines nécessitent ACTIVER LE MOUVEMENT DE RANGES. Je veux juste dire que ce n'est pas une bonne idée de s'appuyer sur un détail d'implémentation qui peut changer à l'avenir.
D.Mika
@ D.Mika Je suis sûr que s'il y a des opérations où le ROWIDpourrait être changé, un bon DBA les rechercherait et ferait ce qu'il pourrait pour les éviter s'il y avait la possibilité qu'ils affectent une table statique comme je l'ai décrit. seule l'application doit fonctionner. Une exportation de table peut être effectuée avec une SELECTinstruction à la place. L'importation se produirait une fois et plus jamais. Je comprends votre point de vue, il faut absolument faire attention, mais les problèmes sont loin d’être inévitables.
vapcguy
35

Cette syntaxe est disponible dans 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;

^^ Je voulais juste démontrer que la ligne ou les lignes (pluriel) peuvent être utilisées quelle que soit la pluralité du nombre de lignes souhaité.)

mancini0
la source
1
select * from some_table chercher la première ligne seulement; son ne fonctionne pas dans mon devloper swl ni dans sql plus donc une erreur lors de la récupération.
nikhil sugandh
Utilisez-vous Oracle 12c?
mancini0
Je ne sais pas vraiment mais quand je l'ouvre, cela montre comme ceci: SQL * PLus Release 10.1.0.4.2 n'est-ce pas 12 c
nikhil sugandh
correct - vous utilisez probablement la version 10.1.xxx, vous pouvez SELECT * FROM V $ VERSION
mancini0
10

nous avons 3 choix pour obtenir la première ligne de la table Oracle DB.

1) select * from table_name where rownum= 1est le meilleur moyen

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
la source
Merci pour les réponses: au point 3) "nowrum = 1" devrait probablement être changé en "rownum = 1".
Andre Nel
7

Autant que je sache, la dualtable dans Oracle est une table spéciale avec une seule ligne. Donc, cela suffirait:

SELECT user
FROM dual
ypercubeᵀᴹ
la source
ce n'est pas vrai, sélectionnez l'utilisateur de dual devrait vous donner tous les utilisateurs
Ben
Il en va de même pour Wikipediaa bout dual in Oracle
ypercubeᵀᴹ
1
.. et juste essayé sur mon système, fonctionne comme ypercube et toutes les mentions de documentation connexes. @Ben
Sathyajith Bhat
1
@Ben dual n'est pas une vue de catalogue, il n'affichera pas "tous les utilisateurs". Vous utiliseriez une vue comme ALL_USERS à cette fin.
makrom le
7

👌 La réponse est:

Vous devez utiliser une requête imbriquée comme:

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

=> En PL / SQL "ROWNUM = 1" n'est PAS égal à "TOP 1" de TSQL.

Vous ne pouvez donc pas utiliser une requête comme celle-ci: "select * from any_table_x where rownum = 1 order by any_column_x;" Parce qu'oracle obtient la première ligne, puis applique ordre par clause.

Fuat
la source
1
Veuillez ajouter des précisions à votre réponse
hgwhittle
Une syntaxe inhabituelle doit être évitée sans raison valable. Dans ce cas, il serait utile de fournir soit un cas de test, soit un numéro de bogue. Je me souviens vaguement de quelques problèmes étranges avec rownum = 1, mais nous ne devrions plus laisser les anciens bogues affecter notre code.
Jon Heller
7
@hgwhittle, La raison pour laquelle Fuat a raison est que ROWNUM ne se soucie pas de «ordery by», il saisit juste le premier enregistrement qu'il peut trouver et le renvoie immédiatement. Donc en d'autres termes, le qualificatif ROWNUM n'a aucun respect pour la commande "Trier par". J'aurais aimé que ce ne soit pas le cas, mais Fuat est correct, pour utiliser la requête imbriquée.
Eric Milliot-Martinez
5

Il n'y a pas de limit 1condition (c'est MySQL / PostgresSQL) dans Oracle, vous devez spécifier where rownum = 1.

Oh Chin Boon
la source
5

"FirstRow" est une restriction et par conséquent, il est placé dans la whereclause et non dans la selectclause. Et ça s'appelle rownum

select * from dual where rownum = 1;
gdoron soutient Monica
la source
1
Notez que cela ne fonctionnera pas comme prévu en combinaison avec ORDER BY, car la commande n'a lieu qu'après la clause where. En d'autres termes, pour obtenir le début d'une certaine requête triée, rownum est totalement inutile.
Nyerguds
@Nyerguds, ce n'est qu'à moitié vrai. Vous pouvez utiliser l'ordre avant le Whereavec une requête Afficher.
gdoron soutient Monica le
4
Quoi, alors SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Eh bien, cela peut fonctionner, mais cela semble assez stupide, tbh.
Nyerguds
2

Si une ligne suffit, essayez:

select max(user)  
from table;

Aucune clause where.

Raihan
la source
9
Il ne vous faudra sûrement que quelques secondes pour essayer cela par vous
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
la source
1

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

fonctionnera le mieux, une autre option est:

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

dans les scénarios où vous voulez différents sous-ensembles, mais je suppose que vous pouvez également utiliser RANK()Mais, j'aime aussi row_number() over(...)car aucun regroupement n'est requis.

Tyler
la source
0

Si vous souhaitez récupérer uniquement la première ligne d'un résultat trié avec le moins de sous-requêtes, essayez ceci:

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
la source
Où sysdate_col serait le nom de toute colonne par laquelle vous souhaitez trier et bien sûr, nom_table serait le nom de la table à partir de laquelle vous souhaitez que les données triées proviennent.
Jody Fedor le
-1

Plus flexible que ne l' select max()est:

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
Client
la source