2016-11-05 8 views
3

Ich versuche, den Benutzer in der Datenbank zu erhalten, der das größte Segment in der Datenbank besitzt. Dazu versuche ich:Oracle SQL - Gruppieren mit ROWNUM in Having-Klausel?

SELECT owner, MAX(bytes) 
FROM SYS.DBA_SEGMENTS 
GROUP BY owner 
HAVING ROWNUM <= 1; 

Dies jedoch zurück "not a GROUP BY expression". Warum kann ich nicht nur die erste Zeile auswählen? Wie kann ich diese Abfrage schreiben? Vielen Dank!

+1

'ROWNUM' auf einzelne Zeilen zugeordnet ist aus der Zeilenquelle (in diesem Fall die Basistabelle 'DBA_SEGMENTS'). 'HAVING' bezieht sich auf Eigenschaften von Gruppen, die durch' GROUP BY' erstellt wurden, nicht auf einzelne Zeilen. Sie können 'ROWNUM' nicht in' HAVING' verwenden, genauso wenig wie Sie 'BYTES' oder einen anderen Ausdruck verwenden können, der unterschiedliche Werte für Zeilen innerhalb einer einzelnen Gruppe haben kann. Genau was die Fehlermeldung sagt. – mathguy

Antwort

5

Sie können. In Oracle 12c +, können Sie tun:

SELECT owner, MAX(bytes) 
FROM SYS.DBA_SEGMENTS 
GROUP BY owner 
ORDER BY MAX(bytes) DESC 
FETCH FIRST ROW ONLY; 

Notiere die ORDER BY.

In früheren Versionen benötigen Sie eine Unterabfrage:

SELECT o.* 
FROM (SELECT owner, MAX(bytes) 
     FROM SYS.DBA_SEGMENTS 
     GROUP BY owner 
     ORDER BY MAX(bytes) DESC 
    ) o 
WHERE rownum = 1; 
+0

Danke, die frühere Version funktioniert. Weißt du, warum 'HAVING ROWNUM <= 1;' nicht funktioniert? –

+0

Ich habe '' rownum'' nur in 'SELECT' und' WHERE' Klauseln verwendet. Es ist eine Pseudo-Spalte, die von Oracle selbst verwaltet wird, so dass es nicht verwunderlich ist, dass die Semantik etwas seltsam ist. In der Dokumentation wird die Klausel "have" nicht erwähnt: https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns009.htm. –

1

In früheren Versionen können Sie auch (nur einen Durchlauf über die Daten):

select max(owner) keep (dense_rank last order by bytes nulls first) as owner, 
     max(bytes) as bytes 
from sys.dba_segments;