Fehler bei erweiterter Select-Abfrage

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Antworten
hubert17
Beiträge: 7
Registriert: Di 22. Mär 2022, 13:19

Hallo Zusammen,

ich habe folgende Abfrage

Code: Alles auswählen

select pos.* 
from tree join pos on tree.id = pos.ebindex 
where tree.katid = 1119 and 
tree.ehoeher = (select tree.ID from tree where tree.katid = 1119 and tree.ehoeher = '1' and tree.nummer = 1) 
and tree.nummer = 3 order by sortnr
Diese liefert mir Datensätze.
Da ich nun die Ausgabe der Anzahl der Datensätze begrenzen möchte, habe ich die Abfrage erweitert:

Code: Alles auswählen

select first 5 * from
(select pos.* 
from tree join pos on tree.id = pos.ebindex 
where tree.katid = 1119 and 
tree.ehoeher = (select tree.ID from tree where tree.katid = 1119 and tree.ehoeher = '1' and tree.nummer = 1) 
and tree.nummer = 3 order by sortnr)
Diese gibt nun einen Fehler aus, SQL error = - 104, Token unknown - line 4, column 86, 1.

Der Fehler scheint an der Stelle

Code: Alles auswählen

tree.ehoeher = (select tree.ID from tree where tree.katid = 1119 and tree.ehoeher = '1' and tree.nummer = 1)
zu sein, denn wenn ich die select-Abfrage mit einem richtigen Wert ersetze,

Code: Alles auswählen

tree.ehoeher = 'F891DFDC18334506A91DD444228A7777'
dann ist der Fehler dort.

Kann man gegebenenfalls die Abfrage umstellen?
Bei uns läuft Firebird 2.5.

Wäre für Hilfe und Anregungen dankbar.
Gruß Hubert
bfuerchau
Beiträge: 609
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Versuche es mal mit

Code: Alles auswählen

select first 5  hugo.* from
(select pos.* 
from tree join pos on tree.id = pos.ebindex 
where tree.katid = 1119 and 
tree.ehoeher = (select tree.ID from tree where tree.katid = 1119 and tree.ehoeher = '1' and tree.nummer = 1) 
and tree.nummer = 3 order by sortnr
) hugo
Begründung:
Es heißt ja "first expression " und da du "5 * " angibst, fehlt dem SQL halt noch was.
Hugo steht natürlich nur für ein Synonym. :D
hubert17
Beiträge: 7
Registriert: Di 22. Mär 2022, 13:19

Vielen Dank für deine Antwort.
Werde mir die schreibweise merken. Daran liegt es leider nicht.
Wie schon oben gesagt, liegt es an der Zeile

Code: Alles auswählen

tree.ehoeher = (select tree.ID from tree where tree.katid = 1119 and tree.ehoeher = '1' and tree.nummer = 1)
Ich habe mit diese Select-Abfrage ein View erstellt und dies dann dafür eingesetzt.

Code: Alles auswählen

tree.ehoeher = (select * from view_ehoeher) 
Jetzt funktioniert es zumindest wie gewünscht, würde aber gern auf die VIEW-Erstellung verzichten.

Gruß Hubert
jhoehne
Beiträge: 53
Registriert: Di 11. Dez 2018, 09:19

"First" braucht m.W. ein "Order By", und zwar auf der gleichen Ebene. Bei Dir ist es Teil der Unterabfrage.

Ansonsten probier doch mal, die Unterabfrage durch eine CTE zu ersetzen:

Code: Alles auswählen

with unter as
(
select pos.* 
from tree join pos on tree.id = pos.ebindex 
where tree.katid = 1119 and 
tree.ehoeher = (select tree.ID from tree where tree.katid = 1119 and tree.ehoeher = '1' and tree.nummer = 1) 
and tree.nummer = 3
)
select first 5 * from unter
order by sortnr
--
Joachim
bfuerchau
Beiträge: 609
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Order by ist nicht zwingend und es muss keine CTE sein:

select first 5 * from (
select ....
)

aber der Fehler lag ja irgendwie in
tree.ehoeher = (select ....)
der tritt dann auf, wenn mehr als eine Spalte selektiert wird oder das Ergebnis mehr als 1 Zeile zurückliefert.
Solche Konstrukte sollte man ersetzen mit
where exists (select ....)
wobei meist eine Beziehung zwischen dem Hauptselect und dem Subselect besteht.
hubert17
Beiträge: 7
Registriert: Di 22. Mär 2022, 13:19

Danke für eure Antworten.

Das Ergebnis der inneren Abfrage liefert nur eine Spalte und eine Zeile, einen eindeutiigen Wert als Varchar.

Meine gesamte Abfrage sieht wie folgt aus:

Code: Alles auswählen

select tree.nummer, pos.* 
from tree join pos on tree.id = pos.ebindex 
where tree.katid = 1119 
	and tree.ehoeher = (Select tree.ID from tree where tree.katid = 1119 and tree.ehoeher = '1' and tree.nummer = 1) 
	and tree.nummer >= 1 
	and tree.Nummer < 3
union
Select first 5 * 
from (select tree.nummer, pos.* from tree join pos on tree.id = pos.ebindex 
where tree.katid = 1119 
	and tree.ehoeher = (Select tree.ID from tree where tree.katid = 1119 and tree.ehoeher = '1' and tree.nummer = 1) 
	and tree.nummer = 3  
	order by 1, 8)
order by 1, 8
Diese gibt mir auch Datenesätze aus. Verwende ich nur die untere SELECT-Abfrage nach UNION, dann kommt wieder der Fehler.

Die Abfrage mit WITH liefert einen Fehler, Listenindex außerhalb des gültigen Bereiches (0).
WHERE EXISTS habe ich bis jetzt nicht benutzt. Mal sehen ob ich das in meiner Abfrage einsetzen und umsetzen kann.

Gruß Hubert
bfuerchau
Beiträge: 609
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Da kann man, wie häufig nur wieder raten.
Select first n
ist nur beim 1. Select erlaubt.

Du kannst aber einen
select first n from (
select ...
union [all]
select ...
) hugo

durchführen.
Ein Problem ist natürlich immer ein Subselect (selec...), der auf sich selbst verweist.
In deinem Beispiel taucht 2x tree auf.
D.h., der subselect ermittelt immer denselben Satz, da er keinen Bezug zum Haupselect hat.
Meist bezieht sich aber ein Subselect ebenso auch auf den übergeordneten Select.
Da du tree 2x hast, solltest du auch jeweils einen alias a / b setzen, so dass du eine eindeutoge Beziehung zwischen tree a und tree b hast.

Zu deinem With-Konstrukt kann ich nichts sagen, da du den nicht postest.
jhoehne
Beiträge: 53
Registriert: Di 11. Dez 2018, 09:19

Was kommt, wenn Du das "innere" "order by 1, 8" weglässt?

Was kommt, wenn Du ein paar Aliase reinwirfst, etwa so:

Code: Alles auswählen

select t1.nummer, p1.* 
from tree t1 join pos p1 on t1.id = p1.ebindex 
  where t1.katid = 1119 
  and t1.ehoeher = (Select t2.ID from tree t2 where t2.katid = 1119 and t2.ehoeher = '1' and t2.nummer = 1) 
  and t1.nummer in (1,2)
union
Select first 5 * 
from (
  select t3.nummer, p3.*
  from tree t3 join pos p3 on t3.id = p3.ebindex 
    where t3.katid = 1119 
    and t3.ehoeher = (Select t4.ID from tree t4 where t4.katid = 1119 and t4.ehoeher = '1' and t4.nummer = 1) 
    and t3.nummer = 3  
)
order by 1, 8
--
Joachim
Antworten