sql: "having klausel" ersetzen

hm, habe es soeben an der datenbank testen können. die "´" bei den jeweiligen spaltennamen mag der parser allerdings nicht ;)
jedenfalls bekomme ich leider folgende fehlermeldung:


allgemienr SQL Fehler:
Token unknown - SELECT - line 19 char 4


hm, ich als halb-noob sehe syntaktisch keine fehler, also klammer zu wenig o.ä.
ebenso sind die bezeichner alle korrekt. lässt dies etwa nur den schluß zu, dass subselects nicht unterstützt werden? :(
Übrigens: Man kann having nutzen! Sorry, ich hatte es bis dato nur falsch eingesetzt. Falls ihr damit noch Ideen habt....
Aber ich sehe bei Having halt das prob, dass wenn ich mit group by arbeite, ich ja ALLE splaten im SELECT, welche nicht in GROUP BY vorkommen, mit einer Aggregat-Funktion (MAX, MIN etc.) ausstatten muss?! Nur bringt mir das wohl wieder nen falsches Ergebnis :(
Hier zur Sicherheit nochmal der Code, wie ich ihn eingegeben habe. Wie gesagt sollte er identisch zu deinem sein, außer dass die "´" rauseditiert sind:

Code:
SELECT
	personal.personalnr,
	personal.nachname,
	personal.vorname,
	personal.kostenst AS KS_Personal,
	personal.eintritt1,
	personal.persstatus,
	auftrag.auftragnr,
	auftrag.kostenst AS KS_Auftrag,
	auftrag.vonDatum AS vonDatum
FROM
	personal
	INNER JOIN
		einsPers
		ON
			personal.personalnr = einsPers.personalnr
	INNER JOIN
		(
			SELECT
				personal.personalnr,
				auftrag.auftragnr,
				MAX(auftrag.vonDatum) AS vonDatum
			FROM
				personal,
				einsPers,
				auftrag
			WHERE
				(
						personal.persstatus = 2
					OR 	personal.persstatus = 7
				)
				AND auftrag.auftstatus = 2
				AND personal.personalnr = einsPers.personalnr
				AND auftrag.auftragnr = einsPers.auftragnr
			GROUP BY
				personal.personalnr
		) AS innerauftrag
		ON
				innerauftrag.personalnr = einsPers.personalnr
			AND	innerauftrag.auftragnr = einsPers.auftragnr
	INNER JOIN
		auftrag
		ON
			auftrag.vonDatum = innerauftrag.vonDatum
ORDER BY
	personal.nachname
	ASC
 
Ohne ein Subselect wird dir HAVING nicht helfen, de es deine Bedingung nicht auf die jeweilige Gruppe beschränkt, sondern die gesamte Tabelle betrachtet.

Vll habe ich es übersehen, aber ich weiß leider nicht mit welchem RDBMS du arbeitest, was jedoch eine sehr gute Information wäre um zu wissen welche Mittel zur Verfügung stehen.
 
soweit ich es in einem nebensatz las, handelt es sich um eine sybase db.
die software schimpft sich landwehr l1 und man kann an deren db abfragen und prozeduren schicken. die mir zur verfügung stehende doku ist leide mehr als mau. morgen früh werde ich nochmal genau nachschauen...
könnte man ggf. sowas machen wie das subselect pozedur-mäßig abzubilden?
 
1 Zusammenhänge und Aufbau der Datenbank in L1
Bei L1 wird die Datenbank „Interbase“ von Borland verwendet. Rufen Sie L1 auf, wird
zunächst die globale Datenbank „global.gdb“ geöffnet, geben Sie dann die entsprechende
Firmennummer in der Startmaske ein, wird die firmen- oder mandantenabhängige Datenbank
ebenfalls geöffnet, bei Firma 1 ist dies die Datenbank „mand1.gdb“, bei Firma 2 „mand2.gdb“
usw.
[....]
Jede Interbase-Datenbank besteht physikalisch gesehen nur aus einer einzigen Datei mit der
Endung „*.gdb“. Intern gibt es in dieser Datei jedoch etliche sogenannte Tabellen, in denen
Daten verarbeitet werden. Die Tabellen wiederum bestehen aus sogenannten Feldern. Die
Informationen, die Sie im L1 eingeben, werden wiederum in den einzelnen Datenfeldern
gespeichert. Mit einem SQL - Editor wie z.B. „LCS-SQL“ lässt sich ein Blick ins „Innere“
der Datenbank werfen. Sie sehen dann, welche Tabellen in der Datenbank vorhanden sind,
welche Felder die einzelnen Tabellen besitzen und welche Inhalte in den Feldern gespeichert
sind. Mehr zu „LCS-SQL“ und weiteren Tools später.
Besagtes LCS-SQL ist auch das Tool, mit dem ich da arbeite. Wobei dieses "Tool" eher ne selbstgebaute Krücke als ein Ferrari ist.
@argh: sorry for doppelpost :(
@urgh: ich lese gerade hier was zur verwendetetn db. ich weiss nur nicht, welche version die hier haben, finde ich vielleicht noch raus. momentan gucke ich mir die 2009er an - embedded sql. dort gibts auch was zu subqueries...
http://docs.embarcadero.com/products/interbase/
@orgh: Kommando zurück - das rdbms ist dieses hier: SQL Server Version: WI-V1.5.0.4306 Firebird 1.5
GDS32.dll Version: Firebird WI-V6.3.0.4306

http://www.firebirdsql.org/ version 1,5
 
Last edited:
Ich bin leider noch nicht ganz wach, aber ich denke dass es so passen sollte.
Da ich keine Interbase Datenbank habe kann ich dies nicht testen, aber soweit ich sehe sollte es sich jetzt an den 2009er Syntax richten.

Code:
SELECT DISTINCT
	personal.personalnr,
	personal.nachname,
	personal.vorname,
	personal.kostenst AS KS_Personal,
	personal.eintritt1,
	personal.persstatus,
	auftrag.auftragnr,
	auftrag.kostenst AS KS_Auftrag,
	auftrag.vonDatum AS vonDatum
FROM
	personal
	INNER JOIN
		einsPers
		ON
			personal.personalnr = einsPers.personalnr
	INNER JOIN
		auftrag
		ON
		(
			auftrag.vonDatum = 
			(
				SELECT
					MAX(auftrag.vonDatum) AS vonDatum
				FROM
					einsPers,
					auftrag
				WHERE
						auftrag.auftstatus = 2
					AND personal.personalnr = einsPers.personalnr
					AND auftrag.auftragnr = einsPers.auftragnr
			)
		)
WHERE
		personal.persstatus = 2
	OR 	personal.persstatus = 7
GROUP BY
	personal.personalnr
ORDER BY
	personal.nachname
	ASC

Es passiert im Prinzip das Gleiche wie im obigem SQL-Befehl, nur etwas umgestellt, da der Subselect jetzt in der ON-Klausel liegt.

//EDIT
Unter http://www.firebirdsql.org/?op=doc findet man zwar keine exakte Aussage bzgl. des SQL-Syntax, aber
While we are working on full user's and reference guides, the current "standard set" of Firebird manuals still consists of the:
  • InterBase 6.0 manuals (legacy command set and behaviour)
lässt mich vermuten, dass man den SQL-Syntax von Interbase auch hier anwenden kann.
 
schon mal wieder vielen dank für deine mühen. nur leider leider las ich gerade dies:
Many new additions have been made to the SQL language, including support for derived tables (SELECT ... FROM ( SELECT ... FROM)) with multiple layers of nesting and the ability to join nested sets, as defined by SQL200X.
und wo steht das:
http://www.firebirdsql.org/index.php?op=devel&sub=engine&id=fb20_release
kurz gefasst: erst ab version 2.0 wird ein subselect in joins unterstützt :(

ergo bleiben nur 2 Möglichkeiten?:
1. subselect "irgendwie" in die WHERE-klausel packen
2. ne prozedur schreiben
 
Soweit ich es sehe wird die "search_condition" in der ON- / WHERE-Klausel nicht unterschieden, was bedeutet, dass man in beiden Subselects nutzen kann.

Hast du den letzten SQL-Befehl ausprobiert, ob dieser funktioniert?

including support for derived tables (SELECT ... FROM ( SELECT ... FROM)) with multiple layers of nesting and the ability to join nested sets, as defined by SQL200X.
Dies Bedeutet, dass man ein Subselect direkt als Tabelle übergeben kann, womit mein erster Vorschlag mit Firebird 2.0 funktionieren sollte.
Da wir aber schon wissen, dass dies nicht vorliegt hatte ich es zuletzt über die ON-Klausel realisiert.
 
ahso. so kann man das natürlich auch auffassen bzw. erscheint mir auch logischer. dein letzter code führte zu folgendem:

line 24: weder mit noch ohne AS akzeptierte er die benennung vonDatum. ich habe es auch mit anderem namen versucht, aber es kam trotzdem der unknown token-mist.
ohne umbenennung kam das, was ich anfangs schon mal hatte, also dass ALLE spalten, welche nicht mit einer aggregatfunktion (zb MAX(irgendwas)) umgeben sind, wohl im GROUP BY stehen müssen...
allgemeiner sql-fehler:
invalid expression in the select list. (not contained in either an aggregate funcion or the GROUP BY clause


aber insgesamt scheint mir das der richtige weg zu sein :) auf diese art das prob mit dem join/select zu umgehen ist ne coole idee, worauf man erstmal kommen muss:
Code:
INNER JOIN
		auftrag innerauftrag
		ON
		(
			[COLOR="Red"]innerauftrag.vonDatum = [/COLOR]
			(
				SELECT
 
Wenn dies das einzige Problem ist, dann entfernen wir einfach GROUP BY und nehmen dafür DISTINCT ^^

Code:
SELECT DISTINCT
	personal.personalnr,
	personal.nachname,
	personal.vorname,
	personal.kostenst AS KS_Personal,
	personal.eintritt1,
	personal.persstatus,
	auftrag.auftragnr,
	auftrag.kostenst AS KS_Auftrag,
	auftrag.vonDatum AS vonDatum
FROM
	personal
	INNER JOIN
		einsPers
		ON
			personal.personalnr = einsPers.personalnr
	INNER JOIN
		auftrag
		ON
		(
			auftrag.vonDatum = 
			(
				SELECT
					MAX(auftrag.vonDatum)
				FROM
					einsPers,
					auftrag
				WHERE
						auftrag.auftstatus = 2
					AND personal.personalnr = einsPers.personalnr
					AND auftrag.auftragnr = einsPers.auftragnr
			)
		)
WHERE
		personal.persstatus = 2
	OR 	personal.persstatus = 7
ORDER BY
	personal.nachname
	ASC

Ich habe jetzt übrigens eine Firebird 1.5 Datenbank eingerichtet und es getestet, bei mir läuft es.
 
Ja, das habe ich genommen.
Da ich nicht weiß ob die Daten geschützt sind habe ich den Anhang gelöscht.

Mich wundert es nicht, dass dort so viele Datensätze enthalten sind, denn pro Person wurde erfüllt, dass nur die Aufträge mit dem zug. höchsten Wert der vonDatum Spalte genommen werden.
Da jedoch mehrere Aufträge diese Bedingung erfüllen werden eben alle mehrere angezeigt.

Ich hätte ja erwartet, dass dort ein UNIX Zeitstempel enthalten ist, denn man beginnt zur gleichen Sekunde sicherlich keine zwei Aufgaben.
Man könnte jetzt überlegen, ob man sich dann nicht nach der Auftragsnummer richten möchte, denn die wächst ja sicherlich autom. und ist - davon gehe ich mal aus - einmalig.
Dann könnte man auch sagen, dass die höchste Auftragsnummer den neusten Auftrag darstellt.

Code:
SELECT DISTINCT
	personal.personalnr,
	personal.nachname,
	personal.vorname,
	personal.kostenst AS KS_Personal,
	personal.eintritt1,
	personal.persstatus,
	auftrag.auftragnr,
	auftrag.kostenst AS KS_Auftrag,
	auftrag.vonDatum AS vonDatum
FROM
	personal
	INNER JOIN
		einsPers
		ON
			personal.personalnr = einsPers.personalnr
	INNER JOIN
		auftrag
		ON
		(
			auftrag.auftragnr = 
			(
				SELECT
					MAX(auftrag.auftragnr)
				FROM
					einsPers,
					auftrag
				WHERE
						auftrag.auftstatus = 2
					AND personal.personalnr = einsPers.personalnr
					AND auftrag.auftragnr = einsPers.auftragnr
			)
		)
WHERE
		personal.persstatus = 2
	OR 	personal.persstatus = 7
ORDER BY
	personal.nachname
	ASC
 
hm, datenschutztechnisch haste recht, thx. auch wenn im endeffekt diese datensätze ohne weitere infos wohl praktisch nix wert sind.
zeitstempel würde keinen sinn machen, denn das programm dient zur personalplanung. also zb ein mitarbeiter ist 7 tage an auftrag A und die nächsten 3 an auftrag B usw.
des weiteren arbeiten mehrere ma an einem auftrag. dies wird durch die tabelle einsPers (=einsatzpersonal) abgebildet/verknüpft, also fremdschlüssel auftragNR und personalNR.
 
Ich sehe dort nicht ganz den Punkt?
Derzeit steht in "vonDatum" scheinbar nur Tag, Monat und Jahr. Wenn man dies nun noch um Stunden, Minuten und Sekunden erweitern würde, dann hat man damit doch nur geschaffen, dass man bei unterschiedlichen Aufgaben, welche am gleichen Tag beginnen, bestimmen kann welche Aufgabe zuletzt angefangen wurde.

Denn "vonDatum" ist ja derzeit ebenso nichts anderes als ein Zeitstempel, nur ein sehr grober.


Aber gut, der SQL-Befehl passt soweit, wie es dann mit der Unterscheidung der Werte weiter geht musst du wissen.
 
ich glaube, ich habe mich zu ungenau ausgedrückt. oberstes ziel ist es, zu jedem ma den aktuellsten auftrag (=MAX(vondatum)) zu bekommen. dies können selten auch mehrere sein. zur erinnerung folgender code, der unseres erachtens dies realisiert:
Code:
SELECT DISTINCT personal.personalnr, MAX(auftrag.vonDatum)
FROM (personal INNER JOIN einsPers ON personal.personalNR=einsPers.personalNr) INNER JOIN auftrag ON auftrag.auftragNr=einsPers.auftragNr  
WHERE (personal.persstatus = 2 OR personal.persstatus = 7)  AND auftrag.auftstatus= 2 
GROUP BY personal.personalnr  				
ORDER BY personal.personalnr ASC
Als weitere ziel sollen halt sämtliche spalten aus dem äußeren select mit angezeigt werden.
 
Anhand der Datensätze scheint es aber so, als würden hier sehr viele mehrere aktuelle Aufgaben haben.
Der obere SQL-Befehl ist mMn soweit jedenfalls korrekt und liefert genau das, was du willst.

Kontrolliere bitte einmal einen der fraglichen Datenteile per Hand.
 
Anhand der Datensätze scheint es aber so, als würden hier sehr viele mehrere aktuelle Aufgaben haben.
Der obere SQL-Befehl ist mMn soweit jedenfalls korrekt und liefert genau das, was du willst.

Kontrolliere bitte einmal einen der fraglichen Datenteile per Hand.

meinst du jetzt meinen direkt über deinem von mir zitierten post? davon gehe ich auch aus :)
wenn ich diese abfrage starte, kommt auch ein adequates ergebnis. aber wenn ich besagte andere spalten auch noch dazu haben will gehts in die hose. ich schicke dir gleich mal als beweis das ergebnis via pn....
 
Nein, ich meine diesen: http://www.united-forum.de/showpost.php?p=1948179&postcount=33

Durch die "GROUP BY personal.personalnr" in deinem SQL-Befehl Anweisung blendest du lediglich alle anderen korrekten Einträge weg, da du pro "personalnr" nur noch eine Zeile zulässt, so ist es nicht möglich, dass pro Person mehrere aktuelle Aufträge anzeigt werden, auch wenn diese Vorhanden sind.

Wie schon gesagt, wenn du - was ja derzeit der Fall ist - mehrere Ergebnisse zurück bekommst, dann liegt dies daran, dass entweder die "auftrag.vonDatum" nicht korrekt gefüllt wird (d.h. das hier nicht das richtige Datum eingetrage wird, wovon ich aber erstmal nicht ausgehe), oder "auftrag.vonDatum" nicht genau genug ist.

Daher wäre es angebracht den Vorgang für eine Person von Hand zu prüfen, damit man sieht, warum so viele Einträge "MAX(auftrag.vonDatum)" entsprechen
 
OMG.
du hast vollkommen recht! die zuständige mitarbeiterin teilte mir soeben mit, nachdem ich deine letzten gedanken ihr unterbreitet hatte, dass sie anstatt auftrag.vonDatum einsPers.DatumVon meint. argh. ich geh mal eben kurz was kaputtschlagen...
 
Back
Top Bottom