SQL Oracle ORA-00907

Helios co.

Lt. Commander
Registriert
März 2005
Beiträge
1.863
Zunächst ein herzliches Hallo an alle.

Ich habe leider eine Query, die den genannten Fehler verursacht.

Code:
SELECT * FROM tabelle1 where id = (SELECT id FROM tabelle2 WHERE ROWNUM < 2 GROUP BY popular_days ORDER BY popular_days);

Ich weiß, dass dieses Vorgehen in MySQL durchaus üblich ist. In Oracle scheint das so nicht zu klappen.

Gibt es eine Alternative?

Vielen Dank im Voraus für eure Hilfe!

Nachtrag(1):

Ich denke man kann die Query mittels PL/SQL realisieren. Doch leider habe ich kaum Ahnung davon D.h. auch hier wäre ich für einen Tip dankbar!

Nachtrag(2)

Es liegt wohl an der Verwendung von ORDER BY in der Subquery.

Bin also immer noch offen für jeden Ratschlag ;)
 
Zuletzt bearbeitet:
Also die Fehlermeldung besagt das du ne Klammer vergessen hättest. kann das aber nu nicht nachvollziehen. Checke es vllt nochmal
 
Du erhälst durch den Subselect eine Menge von Werten und das an einer Stelle, an der ein skalarer Wert gefordert ist?!

Da wäre dann nur "where id in(..)" bzw. "where id = any(..)" möglich.

Was du aber mit dem order im Subselect vorhast verstehe ich dann wirklich nicht mehr :D
 
Zuletzt bearbeitet:
Gib mal das Ergebnis von
Code:
SELECT id FROM tabelle2 WHERE ROWNUM < 2 GROUP BY popular_days ORDER BY popular_days
aus. Wenn mehr oder weniger als 1 Wert kommt, dann gehts so nicht.
 
snow1 schrieb:
Gib mal das Ergebnis von
Code:
SELECT id FROM tabelle2 WHERE ROWNUM < 2 GROUP BY popular_days ORDER BY popular_days
aus. Wenn mehr oder weniger als 1 Wert kommt, dann gehts so nicht.

Es geht so oder so nicht, da Oracle nicht für jeden Fall wissen kann, ob da die Menge wirklich auf einen Wert reduziert wurde.
 
Falls die Subquery eine Ergebnismenge werfen würde, würde eine passende Exception geworfen werden, die etwas mit Datentypen/Konvertierung/Singlerow-Multirow (etc.) zutun hat. Intern versucht Oracle den rechten Teil eines Vergleichsoperators passend zum linken Teil zu konvertieren.

Falls also die Subquery eine Ergebnismenge liefern würde (was sie definitiv nicht macht), wäre Oracle nicht in der Lage diese in einen numerischen Wert zu konvertieren.

Das ist zumindest mein Wissensstand, aber bitte berichtigt mich wenn ich falsch liege!

Was du aber mit dem order im Subselect vorhast verstehe ich dann wirklich nicht mehr

Das hat den Sinn, "popular_days"zu sortieren und aus der sortierten Menge den ersten/obersten Wert (Spalte) auszugeben. Dafür auch das ROWNUM.

Viel fragwürdiger ist meines Erachtens das Group By (ich habe die Query nicht selbst geschrieben,soll sie aber zu Oracle migrieren). Group By angewendet auf eine einzige Spalte macht für mich keinen Sinn. Oder liege ich da falsch?

Falls ich das Order By weglasse, so funzt die Query. Nur leider kriege ich dann halt nicht unbedingt das was ich will, da wie gesagt der "popular days" - Wert nicht der ist, den ich benötige um mit dem äußeren Select weiterzumachen.

Es scheint tatsächlich so zu sein, dass Oracle Order By in einem Subselect nicht zulässt. MySQL erlaubt das aber schon.

Mir ist nur nicht klar wie ich das umgehen kann, ohne PL/SQL verwenden zu müssen,das ich wiederum sehr eklig finde. Wäre eurer Meinung nach ein JOIN möglich?
 
Zuletzt bearbeitet:
1 14.12.2010
2 14.12.2010
3 13.12.2010
4 12.12.2010

ich habe mal diese Beispieltabelle erdacht, und würde gerne von dir wissen, welche ausgabe du haben willst?

ich versteh nicht ganz, wenn du nach dem datum gruppierst, was da raus kommen soll.

suchst du id: 1,2 oder suchst du die erste id die in der ersten gruppe vorkäme wenn man nach datum gruppieren würde?

irgendwie ziemlich banane die query :freak:

so wie es hier ist, kannst du das nicht machen. oracle kann nur gruppieren wenn die selektierte Sache auch eine Mengenoperation ist.

mach mal ein count() um die id im subselect und schon funktioniert sie, wenn auch sinnlos.
 
Das group by würde eh nicht funktionieren, alles was mit select geholt wird muss auch in der group by klausel stehen. Select id und später group by popular_days geht nicht.

Machen wir es doch einfach so:

Poste die komplette Tabellenstruktur und das was du haben möchtest.
 
Zuletzt bearbeitet:
Bei Oracle ist es so, dass das resultset zunächst auf rownum < 2 reduziert wird und danach erst das order by und group by behandelt wird. Das hat zur Folge, dass das order by und group by überflüssig ist, weil du vorher das Resultset auf 1 zeile reduziert hast. Das ist bei dem MsSQL TOP 1 Befehl anders, dort wird erst das group by und order by ausgewertet und danach das result set auf top x reduziert.
Wie carum schon sagte, muss zusätzlich das select und group by übereinstimmen. Nach einer id, die wohl unique ist, zu groupieren macht auch keinen Sinn.

Um zuerst das Order By auszuführen musst du folgendes Konstrukt im Subselect anwenden:

Code:
SELECT ... FROM [B]([/B]SELECT ... FROM ... ORDER BY ...[B])[/B] WHERE ROWNUM < X
Bei dir dann:
Code:
SELECT id FROM [B]([/B]SELECT id,popular_days FROM tabelle2 ORDER BY popular_days[B])[/B] WHERE ROWNUM < 2

Da du nun aber eine Zahl mit einem Subselect einer Zahl vergleichst kannst du nicht = benutzen sondern musst IN verwenden.
Das ganze Select sieht dann so aus:
Code:
SELECT * FROM tabelle1 WHERE id [B]IN[/B] (SELECT id FROM (SELECT id,popular_days FROM tabelle2 ORDER BY popular_days) WHERE ROWNUM < 2 );
 
Zuletzt bearbeitet:
Joe-B schrieb:
Da du nun aber eine Zahl mit einem Subselect einer Zahl vergleichst kannst du nicht = benutzen sondern musst IN verwenden.

Um hier noch meinen Senf dazu zu geben: EXISTS ist in den meisten Fällen schneller wie IN ;)
 
Zuletzt bearbeitet:
Ah verdammt, da fällt es mir wie Schuppen von den Augen. Nach dem ich das kleine Beispiel durchgespielt habe (thx @ Corto) ist mir auch aufgefallen, dass ROWNUM ganz anders ausgewertet wird als LIMIT. Sprich genauso wie Joe-B es sehr einleuchtend beschrieben hat (an dieser Stelle besonderen Dank!).

So gesehen macht das ROWNUM an der Stelle natürlich keinen Sinn in Kombination mit Order By!

Gibt es einen tieferen Grund, warum alle Spalten des Select Anteils auch in den Group By Teil müssen? Sprich scheinbar sahen die MySQL Entwickler das nicht so eng wie die von Oracle?


Vielen Dank an alle! Ihr habt mir wirklich sehr geholfen!
 
Helios co. schrieb:
Gibt es einen tieferen Grund, warum alle Spalten des Select Anteils auch in den Group By Teil müssen? Sprich scheinbar sahen die MySQL Entwickler das nicht so eng wie die von Oracle?

MySql ist nicht so restriktiv wie z.B. Oracle.

Wie sähe denn das Ergebnis von
SELECT id FROM tabelle2 WHERE GROUP BY popular_days

z.B. auf den folgenden Daten deiner Meinung nach aus?
id;popular_days
1;1
2;1
3;1
4;2
5;2

Weil Group by ja gruppiert (surprise, surprise) macht das auch gar keinen Sinn. Deshalb musst du immer eine Aggregatsfunktion im Select verwenden, wie z.B. select max(id) from tabelle2 WHERE GROUP BY popular_days
 
@snow1

Die Query
SELECT id FROM tabelle2 GROUP BY popular_days
auf deinem Testdatensatz müsste eigentlich die ids 1 und 4 liefern.

Was tatsächlich zunächst wenig Sinn macht. Es bleibt für mich nur die Frage ob die Jungs, die diese Query geschrieben haben, das auch so wollen, warum auch immer.
 
Helios co. schrieb:
@snow1

Die Query

auf deinem Testdatensatz müsste eigentlich die ids 1 und 4 liefern.

Wat?!? Wie kommst du denn bitte auf 1 und 4?

SELECT MIN(id) FROM tabelle2 GROUP BY popular_days
würde das liefern, aber doch nicht die ursprüngliche query
 
Das Problem ist, dass folgendes passiert wenn nach popular days groupiert wird:
Die ersten 3 Zeilen mit popular days = 1 versucht oracle zu gruppieren. Das heißt Oracle versucht nun diese Zeilen groupiert als eine Zeile auszugeben.
Das geht aber nicht, da sich in id drei verschiedene Werte befinden, für welchen Wert sollte sich Oracle dann entscheiden? Oracle kann ja nicht per Zufall mal die eine und mal die andere Zahl ausgeben. Deshalb brauchst du, wie snow1 gesagt hat, eine Aggregatfunktion die aus den drei Werten einen Wert macht: z.B. Max(id), COUNT(id),AVG(id), SUM(id).
 
Yap, abermals mein Fehler.

MySQL würde 1 und 4 liefern, Oracle natürlich eine Exception :)

Wobei mir jetzt auch einleuchtet warum! Abermals vielen Dank für eure Erklärungen.
 
Zurück
Oben