PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Oracle 8i - Zuerst Sortieren dann Tupelanzahl beschränken?



sticky bit
24-05-2005, 16:06
Ich habe da ein Problem bzgl. eines Querys auf ner Oracle 8i.

Am besten ich erläutere es an einem Beispiel.
Also stellt Euch vor ich habe eine Tabelle, nennen wir sie `foo`, deren Inhalt der Spalte `bar` mit verschiedenen Werten gefüllt ist, etwa so:


.__________.
| bar |
+----------+
| Hose |
| Rock |
| Hemd |
| Tisch |
| Hund |
| Katze |
| Maus |
| Rechner |
| Mann |
| Frau |
| Papier |
| Holz |
| Stahl |
| Glas |
| Stuhl |
| Bett |
| Schrank |
| Telefon |
| Buch |
| Stift |
| Baum |
| Haus |
| Auto |
| Stiefel |
| Muetze |
+----------+

Aus dieser Tabelle möchte ich nun eine Menge erhalten, die zum einen bestimmte Bedingungen erfüllt, also nehmen wir als Bsp. alles wo `bar` kleiner gleich 4 Buchtstaben in der Länge ist, und das ganze auf 5 Tupel limitieren. Ausserdem soll sortiert werden, etwa nach `bar`.

Insgesamt sehe der Beispiel-Query also z. B. so aus:


SELECT bar
FROM foo
WHERE LENGTH(bar) <= 4 AND
rownum <= 5
ORDER BY bar;


Dieser würde nun allerdings folgendes liefern:


.__________.
| bar |
+----------+
| Hemd |
| Hose |
| Hund |
| Maus |
| Rock |
+----------+

Man sieht also, dass anscheinend zuerst die Limitierung auf die 5 Tupel greift (rownum <= 5) und dann erst die Sortierung (ist ja auch nicht unlogisch), aber genau da liegt mein Problem, die Menge die ich bräuchte sollte eben zuerst sortiert und dann erst auf ihre Tupelanzahl eingeschränkt werden.
So dass eben sowas dabei rauskommt:


.__________.
| bar |
+----------+
| Auto |
| Baum |
| Bett |
| Buch |
| Frau |
+----------+


Bisher fällt mir eigentlich nur eine Möglichkeit ein, nämlich zuerst alles in eine Unterabfrage zu packen und sortieren und dann erst eine beschränkte Anzahl Tupel aus der Menge der Unterabfrage wieder abfragen. Würde dann also so aussehen:


SELECT bar
FROM (SELECT bar
FROM foo
WHERE LENGTH(bar) <= 4
ORDER BY bar)
WHERE rownum <= 5;

Funktioniert zwar, macht aber alles grottenlangsam.
Es ist ja nur ein stark reduziertes Beispiel, der Query um den es eigentlich geht ist recht kompliziert und ohnehin nicht gerade schnell und es geht ausserdem um einige 10K Datensätze...

Also vielleicht fällt jemanden ja ne Möglichkeit ein das irgendwie effizient zu lösen?

elrond
25-05-2005, 06:30
versuch's mit limit:

select * from foo where bar like '%xxx%' limit 5

sticky bit
25-05-2005, 09:21
Danke für die Antwort, aber Oracle und LIMIT passt nicht!

elrond
25-05-2005, 09:28
wieder was dazugelernt...

hat oracle da ggf. etwas ähnliches? ich kenne das bei MS-SQL , da heiß es "select top 10 * from ... "

michael.sprick
25-05-2005, 09:49
nee - sowas kann oracle nicht. mit 8i ist die Inner Query, so wie Du sie hast, glaubich die einzige Möglichkeit. In der 9er Version muss man es auch über eine InnerQuery lösen, ging aber noch etwas anders (und schneller)...

sticky bit
25-05-2005, 13:22
wieder was dazugelernt...

hat oracle da ggf. etwas ähnliches? ich kenne das bei MS-SQL , da heiß es "select top 10 * from ... "Naja, es geht eben über ein Vergleich auf die rownum, ist ne "virtuelle" Spalte die in jeder Tabelle (auch Views, Sub-Select-Mengen etc...) enthalten ist und eben die Position des Tupels beschreibt...

@michael.sprick: Wie ginge es denn auf ner 9i evtl. schneller?

Christoph
25-05-2005, 13:36
Die Oracle Doku sagt ausdrücklich, dass rownum nicht nach dem Sortieren berechnet wird, sondern davor und deshalb nciht zum Selektieren der Größten Werte verwendet werden kann.

LIMIT ist soweit ich weiss SQL3.

michael.sprick
25-05-2005, 16:12
genau deswegen ja die InnerQuery...