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.
Nachdem ich über WITH RECURSIVE (SQL99 glaub ich) gestolpert bin, weiß ich zumindest, dass es geht.
Allerdings haben wir das in der Vorlesung nie gemacht, und mir fällt grad beim besten Willen nicht ein, wie man’s ohne die Rekursion hinbekommen könnte…
Einen Haufen Axiome wollen sie ja wohl nicht… Aber was sonst?!
Hoho: wir bilden die transitive Hülle der Nachfolger-Relation und zählen einfach ab.
Schätze sie wollen hören das es mit „unserm SQL-Wissen“ nicht geht. Haben sie in der Übung nicht sowieso mal behauptet das „unser SQL“ nicht turingvollständig ist?
Wahrscheinlich das was sie uns in der Übung an „Mengeneigenschaften“ verkaufen wollten.
Dürfte einfach irgendwas in die Richtung keine Reihenfolge, keine Duplikate und sonst nur intuitiv-motiviertes Abgezappel („wir hatten Mengenlehre in der Grundschule, ey!“) gewesen sein. (mit Vorbehalt: ich interpretiere das als „bring your own ZFC“-Party ;P)
Naja, man kann schon beweisen, dass TC im „normalen“ SQL nicht geht, aber das macht hier http://www.cs.wisc.edu/~cs784-1/ahoUllman.pdf 1 1/2 Seiten Anhang aus… Also ist das wohl auch nicht gemeint mit „Begründung“…
Hätte jetzt einfach flapsig gesagt das wir nicht rekursiv absteigen bzw schleifen können und man kann die Länge von verketteten Listen ohne Zusatzinfo nur dadurch rauskriegen das man alle Pointer abläuft und mitzählt. Zusammengefasst also: für jeder Algorithmus in “linearem” SQL existiert ne maximale Listenlänge ab der er die Listenlänge nicht mehr bestimmten kann.
Mir würde ja jetzt nur einfallen, dass man (unoptimiert) kartesisches Produkt und Selektion macht und einmal (optimiert (?)) einen Join. Lieg ich damit richtig?
Hat jemand eine Idee für die Bonusaufgabe?
Bin mir bei der Frage auch nicht ganz sicher, aber ich hätte es im ersten Teil auch so gemacht wie du, also: CROSS(…) → SEL(…) → PROJ(…). (Sind das überhaupt „Planoperatoren“? In den Folien habe ich dazu kein gescheites Beispiel gefunden.). Optimiert wäre dann halt: JOIN(…) → SEL(…) → PROJ(…). Und die SQL-Abfrage würde ich dann auch direkt mit [m]…JOIN fahrzeuge f ON k.pid = f.pid…[/m] machen. Keine Ahnung, ob das das ist, was die hören wollten, aber was anderes fällt mir dazu nicht ein.
Jetzt hätte ich auch noch eine Frage zu den „Zeigen sie“-Aufgaben: Uns wurden die Regeln ja nur ohne Beweis „hingeworfen“ und intuitiv sind sie ja auch klar und ich könnte das auch wort- und skizzenreich begründen. Aber „zeigen sie“ heißt für mich irgendwie nicht „erklären sie irgendwie“, also wie soll ich das zeigen?
Also zu optimiert hätte ich auf jeden Fall mal gesagt das die ganzen Selects (Geburtsjahr und Fahrzeugtyp oder was das war) zuerst müssen um beim Join dann kleinere Relationen zu haben und vllt sogar vor dem Join auf jeweils Name und PID runterprojezieren das man da schon schön kleine Tupel hat.
Hier mal dummer Pseudocode:
Scan über kleine Relation (sei hier mal oBdA Fahrzeuge angenommen)
für jeden Satz in Fahrzeuge:
wenn Fahrzeugtyp nicht passt, diesen Satz überspringen
auf (Fahrzeug.PID, Fahrzeug.Name) runterprojezieren
Scan über Personen
für Satz in Personen:
wenn Geburtsjahr nicht passt, continue
auf (Personen.PID, Personen.Name) runterprojezieren, für folgende Schleifendurchläufe cachen
wenn Person.PID=Fahrzeug.PID auf jeweils Name runterprojezieren und in Ergebnis aufnehmen
entsprechend in Pseudo-SQL dann:
select kunde.Name, fahrzeug.Name
from ((select pid, name from kunden where kunden.geburtsjahr ...) as kunde) join
((select pid,name from fahrzeuge where fahrzeug.typ = ...) as fahrzeug) on kunde.pid=fahrzeug.pid
IIRC waren die ganzen „Beweise“ bloss Definition über Mengen einsetzen, (fast schon trivial) umformen, wieder Definition rückgängig machen.
Auf welche Aufgabe beziehst du dich denn konkret?
Ja, das schaut gut aus. Dein Pseudo-SQL ist für mich eigentlich echtes SQL
IMHO meinte TheFlow die Zeigen Sie…-Aufgaben von Braindump 2006 (1. Seite, rechte Spalte, ganz oben). Mehr, als der Verfasser des Braindumps niedergeschrieben hat, fällt mir aber auch nicht ein.
Nachdem ich mich da jetzt noch selber verwirrt hatte, hier ein paar Tipps für die anderen “Beweise”:
Das “kartesische Produkt” (ist kein echtes, weil concat “flachklopft”, kommt eher auf Sprachprodukt aus ThI) ist assoziativ weil das concat ne monoidale Struktur erzeugt (kennt man ja als Wortverknüpfung aus ThI), also einfach auf concat runterbrechen und gut.
Der allgemeine Join ist wohl “kommutativ”, weil die Reihenfolge von Attributen in ner Relation keine echte Rolle spielt. Also könnte man das zB mit nem zusätzlichen projectTupel im Join-Prädikat machen. Wobei ich sowieso mal komisch finde das viele Quellen behaupten nur der natural join sei kommutativ, ist wahrscheinlich Definitionssache.
Das hat mich beim Braindump-Anschauen auch schon ziemlich gestört: Ich glaube, kein Mensch käme – auch nicht bei einer Datenbank – drauf, zu sagen, dass jede beliebige Relation kommutativ ist (a < b <=> b < a ?), aber genau das ist doch die Voraussetzung dafür, dass der Join kommutativ sein kann…
Ohne irgendwelche ausdrücklichen Einschränkungen (Multimengen seh ich ja ein…) ist die Aussage meiner Meinung nach einfach falsch…
Liegt wahrscheinlich einfach daran das man nicht über “Position” auf Attribute zugreifen kann/soll.
Insofern gilt nicht a<b <=> b<a sondern vielmehr BinaryRelation(LeftArg,RightArg) <=> BinaryRelation(RightArg,LeftArg) und Aussagen wie a<b sollte man vllt eher als <(LeftArg=a, RightArg=b) <=> <(RightArg=b, LeftArg=a) lesen.