Vinzenz Mai: Oracle 10g, Select, Order By, gib mir die drittletzte Zeile

Beitrag lesen

Hallo Andreas,

gibt es eine Möglichkeit, mit einem select (natürlich mit order by, so daß eine Ordnung gegeben ist) die drittletzte Zeile der Ergebnis-Menge auszuwählen?

SELECT id,starttime FROM tabelle WHERE name='bla' ORDER BY starttime

gibt mir das wunderschön sortierte Ergebnis aus.
Allerdings alle Zeilen.

Bei MySQL ginge das ja mit LIMIT, aber bei Oracle?

ja, LIMIT wünsche ich mir bei anderen DBMSen ebenfalls, nicht nur bei Oracle.

Mit einem dreifach geschachtelten Select scheine ich das zu bekommen, was ich will:

SELECT id, starttime FROM
  (
    SELECT id, starttime FROM
      (
        SELECT id, starttime FROM tabelle WHERE name='bla' ORDER BY starttime DESC
      )
    WHERE ROWNUM < 4 ORDER BY starttime ASC
  )
WHERE ROWNUM < 2

ich brauche von den Datensätzen, die eine bestimmte Bedingung (name='bla') erfüllen, den mit der dritt-jüngsten Startzeit.
Wie krieg ich das ohne das dreifach-Select-Monster hin?

Hmm, ich sehe nicht, wie Du am Dreifach-Select vorbei kommst, allerdings könnte man es schöner (ok, ist Geschmackssache) schreiben:

Schritt für Schritt:

Meine Beispieldaten:

ID      WERT
----------------------
1       Beispiel
2       Text
3       Oracle
4       Informix
5       DB2
6       MS SQL Server
7       MySQL

SELECT  
    id,  
    wert  
FROM  
    beispiel  
ORDER BY  
    wert DESC;

liefert

ID      WERT
-----------------------
2       Text
3       Oracle
7       MySQL
6       MS SQL Server
4       Informix
5       DB2
1       Beispiel

Baue ich ROWNUM ein:

SELECT  
    ROWNUM line,  
    id,  
    wert  
FROM  
    beispiel  
ORDER BY  
    wert DESC;

so erhalte ich

LINE    ID WERT
-----------------------
3       2       Text
4       3       Oracle
1       7       MySQL
7       6       MS SQL Server
5       4       Informix
6       5       DB2
2       1       Beispiel

Klar, ORDER BY schlägt erst spät zu, somit ist ROWNUM hier unbrauchbar.
Selektieren wir also vom sortierten Ergebnis und fügen erst dort ROWNUM ein:

  
SELECT  
    ROWNUM line,  
    i.id,  
    i.wert  
FROM (  
    SELECT  
        id,  
        wert  
    FROM  
        beispiel  
    ORDER BY  
        wert DESC  
) i;  

liefert

LINE    ID      WERT
------------------------------
1       2       Text
2       3       Oracle
3       7       MySQL
4       6       MS SQL Server
5       4       Informix
6       5       DB2
7       1       Beispiel

Leider können wir nicht hier schon auf ROWNUM = 3 einschränken, denn dann erhalten wir

no data found

weil nur die Zeilen in der Ergebnismenge numeriert werden.
Es ist nur möglich, so wie Du es getan hast, auf ROWNUM < 4 einzuschränken, damit die Ergebnismenge möglichst klein wird. Und um diese Abfrage herum packen wir erneut ein SELECT:

  
SELECT  
    o.id,  
    o.wert  
FROM (  
    SELECT  
        ROWNUM line,  
        i.id,  
        i.wert  
    FROM (  
        SELECT  
            id,  
            wert  
        FROM  
            beispiel  
        ORDER BY  
            wert DESC  
    ) i  
    WHERE ROWNUM < 4    -- nur zur Optimierung  
                        -- Beachte: Ein Spaltenalias kannst Du hier nicht  
                        -- verwenden (zumindest in meiner Oracle 10g XE  
) o  
WHERE o.line = 3;       -- hier können wir problemlos auf Gleichheit prüfen  
                        -- Beachte: line ist hier *kein* Aliasname mehr  

liefert

ID      WERT
--------------
7       MySQL

Ob dies der effizienteste Weg unter Oracle ist, kann ich Dir nicht sagen.
Aber sie tut ganz sicher das, was sie soll - und das ist das, was Deine Anforderung ist.

Freundliche Grüße

Vinzenz