Wie wähle ich nur 1 Zeile aus Oracle SQL aus?


110

Ich möchte die Oracle-Syntax verwenden, um nur eine Zeile aus der Tabelle auszuwählen DUAL. Zum Beispiel möchte ich diese Abfrage ausführen:

SELECT user 
  FROM DUAL

... und es hätte ungefähr 40 Platten. Aber ich brauche nur eine Platte. ... UND, ich möchte es ohne WHEREKlausel möglich machen.

Ich brauche etwas im Feld table_name wie:

SELECT FirstRow(user) 
  FROM DUAL

1
Welche Version von Oracle? Die Verwendung von ROWNUM oder ROW_NUMBER (9i +) würde bedeuten, dass eine WHERE-Klausel benötigt wird
OMG Ponies

1
Hast du einen Tisch benannt dual?
Ypercubeᵀᴹ

1
@ypercube dualist die Systemtabelle in Oracle

4
@ Ben, du solltest wirklich keine Tabelle namens erstellen DUAL. Es ist ein bisschen wie #define TRUE 0in C - sicher, es könnte für Sie funktionieren, aber zukünftige Entwickler werden Sie hassen.
Jeffrey Kemp

3
Hast du tatsächlich versucht zu rennen select user from dual? Wenn nicht, versuchen Sie es bitte und sehen Sie, was Sie bekommen. Auf einem Standard-Oracle-System erhalten Sie den Benutzer zurück, mit dem Sie den Befehl ausführen.
Shannon Severance

Antworten:


169

Sie verwenden ROWNUM.

dh.

SELECT user FROM Dual WHERE ROWNUM = 1

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


@ypercube soweit ich das beurteilen kann, tut es. (Zumindest funktioniert es für meine Installation von oracle10g.)

@bdares: es wird funktionieren, ja. Aber nicht deine Antwort mit dem order by.
Ypercubeᵀᴹ

1
Ja. ROWNUM ist eine spezielle Spalte, die der Ergebnismenge hinzugefügt wird, in der die Ergebnisse aufgelistet sind. Sie können es auch verwenden, um mehrere auszuwählen. Wenn Sie beispielsweise die 10 bestbezahlten Mitarbeiter finden möchten, können Sie sagen "Benutzer AUS MITARBEITERN AUSWÄHLEN, WO ROWNUM <= 10 BESTELLEN NACH GEHALTSABSTIEG"
mindvirus

10
@mkdess: Nein, ORDER BYwird nach dem angewendet WHERE.
Ypercubeᵀᴹ

15
Sie würden brauchen:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ

49

Ich fand diese "Lösung" in einem der Kommentare versteckt. Da ich es eine Weile nachgeschlagen habe, möchte ich es ein wenig hervorheben (kann noch nichts kommentieren oder tun ...), also habe ich Folgendes verwendet:

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

Dadurch wird der gewünschte Eintrag [Spalte] aus dem neuesten Eintrag in der Tabelle gedruckt, vorausgesetzt, [Datum] wird immer über SYSDATE eingefügt.


Ich habe festgestellt, dass es auch funktioniert, wenn Sie bestellen ROWID, solange Sie keine Datensätze löschen und sich immer um den zuletzt eingefügten / geänderten Datensatz kümmern.
Vapcguy

@vapcguy: Erwarten Sie nicht, dass ROWID bestellt wird, auch wenn Sie niemals eine Zeile aus der Tabelle löschen! Selbst wenn es jetzt für Sie funktioniert, ist es in zukünftigen Versionen niemals garantiert.
D. Mika

@ D.Mika Eigentlich sollte es keine Probleme geben, wenn es jetzt funktioniert und Sie niemals Datensätze hinzufügen / entfernen / aktualisieren / löschen. Die Datensätze können nur geändert werden, wenn Sie sie tatsächlich ändern. Es gibt dieses Missverständnis, das ROWIDvon Oracle zufällig geändert wird. Ist es nicht. Es basiert darauf, die Zeilen tatsächlich zu ändern, dh Sie löschen eine und fügen dann eine ein. Der eingefügte bekommt den alten ROWID. Es gibt solche Dinge wie statische Tabellen, die niemals aktualisiert werden - wie Staaten in den USA sind ein gutes Beispiel -, wenn es sich ändert, würde es wahrscheinlich sowieso andere Auswirkungen haben, wenn dies in Ordnung ist.
Vapcguy

@ Vapcguy: Nun, das ist fast richtig. Es gibt jedoch auch andere Vorgänge, die die ROWID ändern. Was ist, wenn Sie die Tabelle aus irgendeinem Grund exportieren / importieren? Es gibt andere Operationen, aber einige von ihnen benötigen ENABLE ROW MOVEMENT. Ich möchte nur sagen, dass es keine gute Idee ist, sich auf ein Implementierungsdetail zu verlassen, das sich in Zukunft ändern kann.
D. Mika

@ D.Mika Ich bin mir sicher, wenn es Operationen gibt, bei denen die ROWIDgeändert werden könnten, würde ein guter DBA sie nachschlagen und alles tun, um sie zu vermeiden, wenn die Möglichkeit besteht, dass sie eine solche statische Tabelle beeinflussen, wie ich sie beschrieben habe Nur die Anwendung sollte ausgeführt werden. Ein Tabellenexport kann stattdessen mit einer SELECTAnweisung durchgeführt werden. Der Import würde einmal und dann nie wieder passieren. Ich verstehe, es ist auf jeden Fall Vorsicht geboten, aber die Probleme sind keineswegs unvermeidlich.
Vapcguy

34

Diese Syntax ist in Oracle 12c verfügbar:

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;

^^ Ich wollte nur zeigen, dass entweder Zeile oder Zeilen (Plural) verwendet werden können, unabhängig von der Vielzahl der gewünschten Anzahl von Zeilen.)


1
Wählen Sie * aus einer Tabelle, um nur die erste Zeile abzurufen. Es funktioniert weder in meinem SWL-Entwickler noch in SQL Plus, also Fehler beim Abrufen.
Nikil Sugandh

Verwenden Sie Oracle 12c?
Mancini0

Ich weiß es nicht wirklich, aber wenn ich es öffne, zeigt es wie folgt: SQL * PLus Release 10.1.0.4.2 ist es nicht 12 c
nikhil sugandh

Richtig - Sie verwenden wahrscheinlich Version 10.1.xxx, Sie können * FROM V $ VERSION
mancini0

10

Wir haben drei Möglichkeiten, um die erste Zeile in der Oracle DB-Tabelle abzurufen.

1) select * from table_name where rownum= 1ist der beste Weg

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

Vielen Dank für die Antworten: Unter Punkt 3) sollte "nowrum = 1" wahrscheinlich in "rownum = 1" geändert werden.
Andre Nel

7

Soweit ich weiß, ist die dualTabelle in Oracle eine spezielle Tabelle mit nur einer Zeile. Das würde also ausreichen:

SELECT user
FROM dual

Das ist nicht wahr. Ausgewählter Benutzer aus Dual sollte Ihnen alle Benutzer geben
Ben


1
.. und gerade auf meinem System ausprobiert, funktioniert als ypercube & alle zugehörigen Dokumentationserwähnungen. @ Ben
Sathyajith Bhat

1
@Ben Dual ist keine Katalogansicht, es werden nicht "alle Benutzer" angezeigt. Zu diesem Zweck würden Sie eine Ansicht wie ALL_USERS verwenden.
Makrom

7

👌 Die Antwort lautet:

Sie sollten verschachtelte Abfragen verwenden als:

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

=> In PL / SQL ist "ROWNUM = 1" NICHT gleich "TOP 1" von TSQL.

Sie können eine Abfrage wie diese also nicht verwenden: "Wählen Sie * aus any_table_x aus, wobei rownum = 1 order by any_column_x;" Da Orakel die erste Zeile erhält, wird die Reihenfolge nach Klausel angewendet.


1
Bitte fügen Sie einige Klarstellungen zu Ihrer Antwort hinzu
hgwhittle

Ungewöhnliche Syntax sollte ohne guten Grund vermieden werden. In diesem Fall wäre es hilfreich, entweder einen Testfall oder eine Fehlernummer anzugeben. Ich erinnere mich vage an einige seltsame Probleme mit rownum = 1, aber wir sollten nicht zulassen, dass alte Fehler unseren Code mehr beeinflussen.
Jon Heller

7
@hgwhittle, Der Grund, warum Fuat korrekt ist, ist, dass ROWNUM sich nicht für 'ordery by' interessiert, sondern nur den ersten Datensatz erfasst, den es finden kann, und ihn sofort zurückgibt. Mit anderen Worten, das ROWNUM-Qualifikationsmerkmal hat keinen Respekt vor dem Befehl "Bestellen nach". Ich wünschte, das wäre nicht der Fall, aber Fuat ist richtig, um die verschachtelte Abfrage zu verwenden.
Eric Milliot-Martinez

5

limit 1In Oracle gibt es keine Bedingung (das ist MySQL / PostgresSQL), die Sie angeben müssen where rownum = 1.


5

"FirstRow" ist eine Einschränkung und daher in der whereKlausel nicht in der selectKlausel enthalten. Und es heißt Rownum

select * from dual where rownum = 1;

1
Beachten Sie, dass dies in Kombination mit nicht wie erwartet funktioniert ORDER BY, da die Bestellung erst nach der where-Klausel erfolgt. Mit anderen Worten, um die Spitze einer bestimmten sortierten Abfrage zu erreichen, ist Rownum völlig nutzlos.
Nyerguds

@Nyerguds, das ist nur halb wahr. Sie können order by vor dem Wheremit einer View-Abfrage verwenden.
Gdoron unterstützt Monica

4
Was also SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Nun, das mag funktionieren, aber es sieht ziemlich dumm aus, tbh.
Nyerguds

2

Wenn eine Zeile ausreichen würde, versuchen Sie:

select max(user)  
from table;

Nein wo Klausel.


9
Sicherlich dauert es nur Sekunden, bis Sie das selbst ausprobieren
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; 

1

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

wird die beste Leistung bringen, eine andere Option ist:

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

in Szenarien, in denen Sie verschiedene Teilmengen wollen, aber ich denke, Sie könnten auch verwenden, RANK()aber ich mag auch, row_number() over(...)da keine Gruppierung erforderlich ist.


0

Wenn Sie nur die erste Zeile eines sortierten Ergebnisses mit den geringsten Unterabfragen zurückholen möchten, versuchen Sie Folgendes:

select *
  from ( select a.*
              , row_number() over ( order by sysdate_col desc ) as row_num
           from table_name a )
  where row_num = 1;

Wobei sysdate_col der Name einer Spalte ist, nach der Sie sortieren möchten, und natürlich table_name der Name der Tabelle, aus der die sortierten Daten stammen sollen.
Jody Fedor

-1

Flexibler als es select max()ist:

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.