Korrekturkommentarbausteine zur Klausur WS2223: #### Modellierung: Entitätstyp Stadt fehlt -3 Schlüssel von Stadt? -0.5 Stadt.name als (partieller) Primary Key -0.5 Stadt muss weak mit identifizierender Beziehung "in" sein -1 liegtIn als identifizierende Beziehung -0.5 Stadt weak, Stadt.Landescode nicht nochmal als Attr zu Stadt, sondern als identifizierende Beziehung -1.5 Beziehung "Hauptstadt" fehlt -2 Stadt.Land ist kein Attribut, sondern durch die Beziehung gegeben -0.5 Land.Hauptstadt ist kein Attribut, sondern eine Beziehung zu Stadt -2 Land.Hauptstadt ist kein Attribut, sondern durch die Beziehung gegeben -0.5 (Land <1,1> zu Hauptstadt, aber <0,*> zu Stadt ist etwas inkonsequent) Land.EUmembership fehlt -0.5 Treffen.Stadt als Beziehung+Kardinalitäten -2 Treffen.Teilnehmer nicht nochmal als Attr (müsste dann auch mehrwertig sein), ist ja schon in XXXXX -1 Beziehung zwischen Person und Land fehlt -2 Person.Land nicht nochmal als Attribut, ist ja in der Beziehung -0.5 Beziehung zwischen Meeting und Stadt fehlt -2 Treffen.Landescode nicht als Attribut, sondern über Beziehung->Stadt->Land -0.5 Treffen.Stadt ist kein Attribut sondern in der Beziehung -0.5 Treffen.Teilnehmer ist kein Attribut, sondern in der Beziehung -0.5 Keine Beziehung Treffen->Land, die ist ja über Stadt gegeben -0.5 "Treffen" ist nicht weak (hat ja eine eindeutige id) -0.5 muss ein Entitätstyp sein, um einzubringen, dass an jedem Treffen mehrere Personen teilnehmen. So würde es ja als Relation (_id_, Stadt, Person, ...) angelegt -2P Kardinalitäten: Kardinalität: Land zu Stadt <1,*> -0.5 Kardinalität: Land zu Hauptstadt <0,1> -0.5 Kardinalität: Stadt als Hauptstadt <0,1> -0.5 Kardinalität: Stadt zu Land <1,1> -0.5 Kardinalität: Treffen zu Stadt <1,1> -0.5 Kardinalität: Stadt <0,*> zu Treffen, da nicht in jeder Stadt ein Treffen stattfindet (und aber alle Hauptstädte gespeichert sein sollen) -0.5 Kardinalität: Treffen zu Person <1,*> oder <2,*> -0.5 Kardinalität: Treffen zu EU-Politiker/IntVertreter <1,*>, sonst würde man es ja nicht speichern -0.5 Kardinalität: Person <0,*> zu Treffen, da nicht jeder Mitarbeiter irgendwann mal an einem Treffen teilnimmt -0.5 Kardinalität: Land <0,*> zu Person, da nicht aus jedem Land eine Person gespeichert sein muss -0.5 Kardinalität Person zu Land <1,1> -0.5 Kardinalität: Stadt zu Land <1,1> (sonst passt das mit dem "weak" auch nicht) -0.5 Kardinalität: Stadt als Hauptstadt <0,1> -0.5 Treffen.Themen muss mehrwertiges Attribut sein -0.5 Treffen.Themen fehlt -1 Treffen.ort/adresse fehlt -0.5 "nimmtTeil" ist keine 3-stellige Beziehung: Dann müsste man nachher Tripel (Treffen, EUPol, IntVertr) speichern. -2P -> zwei getrennte Beziehungen, oder eine zu Person "Treffen" muss ein Entitätstyp sein, um einzubringen, dass an jedem Treffen mehrere Personen teilnehmen. So würde es ja als Relation (_id_, Stadt, Person, ...) angelegt -2P ################################################## ### Transformation in das relationale Modell Tabelle Land: 1P, PK 0.5, FK Hauptstadt 1 = 2.5 Tabelle Stadt: 1P, PK 0.5, FK Land 1 = 2.5 Tabelle Treffen: 1P, PK 0.5, FK Stadt 1 = 2.5 Tabellen TeilnEU+TeilnExt 2P, PK 0.5, 2x1P FKs = 4.5 Tabelle Themen: 0.5P, PK 0.5, FK id 1 = 2 ### Alle, die nur 3 Tabellen Land, Stadt, Treffen haben, bottom-up mit Punktesammeln bewerten: wenn id alleiniger key sein soll, passen schon die ersten beiden Zeilen nicht -0.5. Teilnehmer: n:m-Beziehung -> Spalte/n rausnehmen, separate Tabelle/Tabellen. -0.5 ### eine Teiln-Spalte als Liste, Ref auf person FK Person(name): es gibt keine Tabelle Person => Zwei separate Tabellen, FKs auf EUPolitiker bzw IntVertreter -0.5 ### 2 getrennte Spalten: Nicht beide Arten von Teilnehmern in einem Tupel kombinieren (wenn 2 EUPolitiker, und 3 Interessenvertreter dabei sind, wer dann mit wem? Oder alle 6 Kombinationen?) -0.5 "Themen" (mehrwertig) muss separate Tabelle sein. -0.5 ### Top-Down-Bewertung bei prinzipiell richtigem Gesamtentwurf: Beispieltupel fehlen -3P Stadt: Land muss auch im PK sein -0.5 Stadt: FK Land fehlt -1 Land: FK für Hauptstadt muss auch Code umfassen -0.5 (im PK bei Stadt ist es drin!) Land: FK (Hauptstadt,Code)->Stadt fehlt -1 Treffen: Spalte Land muss auch FK sein, zusammen mit Stadt -0.5 Treffen: Spalte Land fehlt, muss auch im FK sein, zusammen mit Stadt -1 Land.hauptstadt und das boolean-Attribut stadt.isCapital ist redundant. -0.5 separate Tabelle für "Themen" (mehrwertig) fehlt (Tab, PK, FK, Ref) -2P Tabelle "Person" als Oberklassentabelle anzulegen als Ziel für FKs ist OK. ## wenn Teiln.FK auf Person.name da ist: FK nimmtTeil(Person) -> Person(Name): FK teilnehmen(Teilnehmer) -> wohin? -0.5 Es gibt keine Tabelle Person => FKs müssen auf EUPolitiker bzw IntVertreter zeigen => geht nur wenn man nimmtTeil auf 2 Tabellen aufspaltet -1 für eine Tabelle weniger ### nimmt Teil als 3-stellige Relation: NimmtTeil kann man nicht als 3-stellige Relation machen (wenn 2 EUPolitiker, und 3 Interessenvertreter dabei sind, wer dann mit wem? Oder alle 6 Kombinationen?) => auf 2 separate Tabellen aufspalten -1 für eine Tabelle weniger, -1 für schlechtes Design (wäre mit Beispieltupeln evtl aufgefallen) Wenn wirdBesprochen.Beschreibung FK ist, müsste es irgendwo eine einspaltige Tabelle "Themen (Name)" geben -0.5 Themen: FK id -> Treffen(id) fehlt -1P Teiln: FK id -> Treffen(id) fehlt -1P Fremdschlüssel Referenzen->Ziele fehlen komplett (6x0.5 : -3P) FK-Ziele zu den angegebenen Fks fehlen (3x) -1.5P (FKs: die Pfeile müssen andersrum sein: referenzierendes Tupel -> referenziertes Tupel) ####################################################### ### Create Table Spalte Land fehlt -0.5 FK Stadt+Land zusammen -0.5 (beides ist Key von Stadt) Stadt NOT NULL -0.5 datum NOT NULL -0.5 Stadt,land NOT NULL -1 adresse, datum, stadt, land not null -2 ort, datum, stadt not null -1.5 adresse, datum, stadt not null -1.5 (FK Stadt+Land FF) Folgefehler wenn nur name key von Stadt ist FK auf Stadt fehlt -1 id int passt mit den Beispieltupeln aber nicht zusammen -0.5 Wenn Teilnehmer hier, dann NOT NULL -0.5 Teilnehmer: ist bei Ihnen eine Liste, also kann REFS Person(name) (einzeln!) nicht funktionieren -0.5 Teilnehmer: ist bei Ihnen eine Liste, also reicht VARCHAR2 (20) nicht aus, und REFS Person(name) (einzeln!) kann auch nicht funktionieren -0.5 Person(Name) als Ziel geht nicht, da es keine Tabelle Person gibt -0.5P => auf 2 Spalten bzw separate Tabellen aufspalten. REFERENCES mit OR geht so nicht -> auf 2 Spalten aufteilen -0.5 Für eine Liste der Teilnehmernamen reicht VARCHAR2(80) nicht aus ... -0.5 ############################################################################### ### Anfrage 1 (Malta) nicht zielführend, 0P distinct fehlt -0.5 Tabellen EUpolitiker und Land haben beide eine Spalte name -> welche im SELECT? -0.5 Tabelle Land fehlt im FROM -0.5 (FF Land müsste auch überprüft werden) Treffen.Land auch überprüfen (ist im PK von Stadt) -0.5 Wenn man den Landescode ('M') von Malta nicht hat, sollte man den Landesname "Malta" verwenden -0.5 dafür ist die Tabelle Land ja da. -0.5 Um die Hauptstadt abzufragen soll nicht die Zeichenkette "Valletta", sondern Land.Hauptstadt verwendet werden. -1 (join+Vergleich fehlen) falls WHERE Stadt=Malta: Hauptstadt von Malta -> Tabelle "Land" auch benutzen -1.5 Gibt alle Teilnehmer aus, nicht nur die EU-Politiker -0.5 Wenn "nimmtTeil" als Ausgangsrelation verwendet wird, muss DISTINCT verwendet werden -0.5 "nimmtTeil" enthält sowohl EUPolitiker als auch Interessenvertreter -> noch auf EUPol filtern t.person ist eine Liste, nicht eine Einzelperson -> Vergleich geht so nicht -1 Das Enthaltensein in einer Liste (die kein erlaubter SQL-Datentyp ist) geht mit IN nicht -1 t.Person ist eine Liste (als String), also geht "=" nicht -1 distinct personen ergibt so nur die unterschiedlichen Listen, aber nicht die Personen -1 Algebra als upload ### Anfrage 2 (mit Qataris) Das gibt an, wie oft jemand an Treffen IN Qatar teilgenommen hat. gesucht war: mit Politikern aus Qatar. (noch 2P) Wenn an einem Treffen mehrere Qataris teilnehmen, werden diese mehrfach gezählt -0.5 Die zweite Person muss Interessenvertreter sein, weil Qataris keine EU-Politiker sind. -0.5 ... and IntVertr.org is null -0.5 Es gibt keine Tabelle Person -> IntVertreter verwenden -0.5 aussen nur EUpolitiker p, dann nt.EUPol=p.Name innen-aussen verbinden -1 Wieder das Problem mit dem Vergleich und der Teilnehmerliste -0.5 ("spart" ein Join) Bei dem Join über die (in Aufg 3 nicht existierende Spalte m.politician_id) funktioniert entweder das "="-Join nicht (wenn listenwertig), oder es werden die Tupel vervielfacht, so dass count(*) nicht funktionmiert -0.5 Die äußere WHERE-Klausel könnte man direkt auch mit HAVING innen machen. Wobei count immer > 0 sein muss, sonst würde ja kein Tupel beim Join rauskommen. Having count(*) > 0 ist fast immer unnötig (ausser man macht etwas mit einem outer join), da Tupel, die kein Join finden, ja rausfallen. Umgekehrt muss man, wenn man auch diejenigen mit count=0 haben will, innen immer ein outer join und count(spaltenname) machen, um nulls nicht mitzuzählen. ### Anfrage 3 (nie in der Ukraine) nochmal alle, die aussen "nimmtTeil" haben, -0.5 s.u. Das sind alle, die mal an einem Treffen teilgenommen haben, das nicht in der Ukraine stattfand. 1P Das gibt diejenigen EU-Politiker aus, die an Treffen in Städten teilgenommen haben, die nicht in der Ukraine liegen (bzw sogar zu denen es keine gleichnamige Stadt in der Ukraine liegt). 1P Es gibt keine Tabelle Person -> EUPolitiker verwenden -0.5 Wenn "nimmtTeil" als Ausgangsrelation verwendet wird, muss DISTINCT verwendet werden -0.5 Wenn "nimmtTeil" als Ausgangsrelation verwendet wird, fallen alle EUPolitiker, die (noch) nie an einem Treffen teilgenommen haben, raus. -0.5 Wenn "Treffen" mit im FROM ist, muss DISTINCT verwendet werden -0.5 Wenn "Treffen" mit im FROM ist, fallen alle EUPolitiker, die (noch) nie an einem Treffen teilgenommen haben, raus. -0.5 ### Anfrage 4 (Algebra nicht Ukraine) Wenn "nimmtTeil" als Ausgangsrelation verwendet wird, fallen alle EUPolitiker, die (noch) nie an einem Treffen teilgenommen haben, raus. -0.5 ### Anfrage 5 (in allen Hauptstädten) Treffen.Land auch überprüfen (ist im PK von Stadt) -0.5 der Ansatz ist richtig ... 0.5P Die ersten acht Zeilen sind richtig. (2P) Das gibt nur die Namen der Politiker aus, die irgendwann an einem Treffen in irgendeiner EU-Hauptstadt teilgenommen haben - noch 1P ### Anfrage 5, 6 2P wenn Division teilweise vertauscht nur EU-Länder -0.5 Das wären diejenigen, die an irgendeinem Treffen in einer europäischen Hauptstadt teilgenommen haben. noch 1P Das wären diejenigen, die an ALLEN Treffen in europäischen Hauptstädten teilgenommen haben. -1 Hauptstadt? -0.5P Baum als Upload Bäume für A1b, A4, A6, double-div keine Baum-Uploads ### Updates Nicht das Treffen soll in Qatar stattgefunden haben, sondern Teilnehmer sollen Qataris gewesen sein. -2 Nur die Treffen löschen, an denen auch mindestens ein Qatari teilgenommen hat -2 Nur die Treffen löschen, an denen E.Kaili auch teilgenommen hat -1 Auch alle Teilnahmen an diesen Treffen löschen. -1.5 Auch diese Treffen löschen -1 Auch die Einträge in "Beteiligte" löschen -1.5 -> das löscht die Teilnahmen-Tupel von Eva Kaili an Treffen, an denen Qataris beteiligt waren. * die anderen Teilnehmer dieser Treffen auch löschen -1 * die Treffen auch löschen -1 Die Kurzform, ein Delete auf mehreren Tabellen auszuführen gibt es (leider) nicht. (Reihenfolge, WHERE anpassen) -1 Wegen der Foreign keys zuerst die referenzierenden Einträge löschen, "Treffen" zuletzt -0.5 Egal, in welcher Reihenfolge man es macht - man muss das spätere WHERE auf die bereits gelöschten Tupel anpassen -0.5 Es gibt keine Person-Tabelle -> IntVertreter für die Qataris verwenden -0.5 man braucht auch hier 2x Teilnehmer: für E.Kaili und für die Interessenvertreter -1 ## die Tabelle "hatThema" für das mehrwertige Attribut hatte fast niemand angelegt: (Die Treffen müssen auch aus "hatThema" gelöscht werden.) auch in "hatThema" gelöscht +0.5 ### komplexes SQL Zeile 5: Land muss EU-Mitglied sein -0.5 ### Theorieaufgabe (einige Teilnehmer haben eine falsche Definition des div-Operators benutzt, nicht als forall b\in S, sondern als \exists b\in S, zum Teil auch ohnr Streichung der wegdividierten Spalten. Für diesen -anderen- Operator gilt die Gleichheit auch, das Vorgehen beim dem Beweis ist auch ganz ähnlich) Der Argumentation liegen mehrere Fehlinterpretationen über den Divisionsoperator zugrunde: * Die Tupel in (R:S):T haben nur noch das Attribut A. * R:S sind alle (a,c)-Tupel, die mit JEDEM b aus S als (abc) in R enthalten sind. * Tupel sind mit benannten Spalten, nicht mit Reihenfolge (daher TxS = SxT) Sie scheinen das div hier eher als einen "mehrzeiligen Filter" im Stil eines "exists" bzw. "IN" zu interpretieren. Einen solchen Operator könnte man definieren (in der RDF-Anfragesprache SPARQL gibt es so etwas als "values ( (...),(...)...)"), und für den würde die Aussage auch gelten: R[b in S][c in T] = R[(b,c) in SxT] Dazu kommt, dass Tupel Slot-Value-Paare sind, nicht Vektoren: (a:1, b:2, c:3) und entsprechend kommt es bei TxS und SxT nicht auf die Reihenfolge, sondern auf die Spaltennamen an. * als EXISTS richtig gemacht: 2P R[b in S][c in T] = R[(b,c) in SxT]