Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.
Welcher SQL-Dialekt ist Prüfungsrelevant?
Auf der Suche nach einer Erklärung zu der vom Herrn Lenz vorgestellte Top-N-Query, bin ich über etliche Möglichkeiten solche Queries so zu gestalten, dass sie mir auch logisch erscheinen, gestolpert.
Bisher kannte ich nur MySql und unsere Tutorin meinte es wird Oracle benutzt.
Jetzt ist meine Hauptfrage was ist in der Klausur erlaubt?
Selbst wenn ich davon ausgehe, dass nur Oracle-SQL erlaubt ist gibt es viele Möglivhkeiten z.b
per rownum oder Fetch only first… oder per rang.
Ist das Ganze wie in der Schule, also:
Nur das was im Unterricht gelehrt wurde, ist als Lösungsweg akzeptabel.
Geht das Ganze nach dem Prinzip:
Solange es richtig und aktuell ist, ist es ok.
Ich finde den Aufbau der Top-N-Query von Herr Lenz nämlich extrem fraglich und bin mir nicht einmal sicher ob diese Version wirklich auch für alle Versionen von Oracle funktioniert(e).
Damals als das bei uns war war ANSI-SQL massgeblich, also weder die Abkuerzungen ‘limit’ (mysql) noch ‘rownum’ (oracle) waren erlaubt, man brauchte zwingend selfjoins. K.A. ob das inzwischen anders ist.
So in etwa. In der Übung wird zwar mit Oracle gearbeitet, allerdings geht es in dieser Vorlesung eher um die Grundlagen und nicht um irgendwelche tolle Funktionen die alles automagisch machen. Dafür gibt es andere Vorlesungen
In der Praxis hat die gezeigte Query eher weniger Relevanz, sollte aber prinzipiell auf quasi allen Datenbanksystem so funktionieren. (Was natürlich nicht für spezifische Funktionen wie z.B. einem RANK in Oralce gilt)
Naja manchmal hilft Automagie schon.
Aber gut ich studier ja Informatik um den Sinn hinter den Sachen zu verstehen und die Theorie und nicht um ein paar Befehle auswendig zu lernen.
Vielleicht mag mir aber jemand noch einmal kurz helfen (vielleicht sogar mit einem kleinen Beispiel), wieso diese Query geht:
Wir haben folgende Tabelle:
Tabelle Pers:
PNr ANr Name Gehalt
0 1 Max 1000
1 5 Mix 1200
2 8 Mex 1100
3 9 Mux 1500
4 2 Mox 1800
Wenn ich jetzt die 2 Bestverdiener pro Abteilung haben will, sieht die Anfrage ja so aus:
SELECT P.ANr, count() as Rang, P.Name
FROM Pers P, Pers A
WHERE P.ANr = A.ANr and P.Gehalt <= A.Gehalt
GROUP BY P.PNr, P.Name, P.ANr
HAVING count() <= 2
Was mir soweit klar ist, ist dass wir 2 Tabellen brauchen um das auszuwerten.
Zuerst wird ein JOIN über die ANr gemacht, wenn ich das richtig verstanden habe, wird hier jedes Tupel mit sich selbst als Tupel verknüpft, da die Tabelle ja 2x dieselbe ist und dementsprechend dieselben Tupel auch immer vorhanden sind.
Also müssten wir jetzt alle Tupel doppelt beschrieben haben richtig?
Also so:
PNr ANr Name Gehalt PNr2 ANr2 Name2 Gehalt2
0 1 Max 1000 0 1 Max 1000
1 5 Mix 1200 1 5 Mix 1200
2 8 Mex 1100 2 8 Mex 1100
3 9 Mux 1500 3 9 Mux 1500
4 2 Mox 1800 4 2 Mox 1800
Jetzt wird gecheckt wo das P.Gehalt <= A.Gehalt ist, in meinen Augen ist dieses Gehalt jetzt aber überall kleiner gleich?
Anschließend gruppieren wir PNr, Name und ANr.
Damit dürfte sich unsere Tabelle, wie sie oben ist erst einmal nicht verändern.
Jetzt zum Schluss werden nur die Gruppen ausgewählt, die weniger als 2 Tupel besitzen.
In meinen Augen also jedes Tupel.
Wäre jemand so lieb und könnte mir erklären wo mein Denkfehler liegt?
Danke schon einmal im Voraus.
Edit:
Sorry mein Fehler, ANr steht nicht für “Arbeiternummer” wie ich ursprünglich dachte, sondern für “Abteilungsnummer” und ich habe den Nebensatz (Spitzenverdiener für jede Abteilung) total überlesen, meine Vorstellung oben sollte also schon richtig sein und es kommt auch das richtige Ergebnis raus. Vielleicht verstehts wenigstens jemand was ich versucht habe zu erklären, dann war der Post nicht ganz umsonst.
Hast du mal auf deine JOIN-Bedingung geschaut? Du schreibst
Denk daran: Ein Join besteht aus einem Kreuzprodukt und einer Join-Bedinung. Wenn die Join-Bedingung nichts ist, was für jedes Tupel nur einmal gelten kann (z.B. Gleichheit von Fremdschlüsseln mit Schlüsselkandidaten), sagt niemand, dass ein Tupel nur mit einem verbunden wird. Denk an’s Kreuzprodukt: Jedes Tupel wird konzeptionell gegen jedes andere geprüft.
Will sagen: Wenn du eine Relation mit n Tupeln mit sich selbst joinst, bekommst du nicht zwingend n Tupel, sondern bis zu n².
Allerdings: Bei einem Beispiel, in dem jede Abteilung nur einen Arbeiter hat, wird die Lösung allerdings nicht sehr aussagekräftig sein
Jap ich meinte das auch auf dieses Beispiel bezogen und hatte die Erklärung gechrieben bevor ich das „pro Abteilung“ gelesen habe.
Trotzdem nochmal danke für die kleine Erläuterung.
@DrunkenMan
Laut einigen Quellen ist die Aggregats-Funktion RANK() in ANSI SQL 2003:
Aber da ich die Anfrage jetzt verstanden habe und es an einem Fehler meinerseits lag, interessiert mich das gar nicht mehr wirklich.