\documentclass{bschlangaul-aufgabe}
\bLadePakete{sql}
\begin{document}
\bAufgabenMetadaten{
  Titel = {Aufgabe 3},
  Thematik = {Schuldatenbank},
  Referenz = 46116-2018-H.T2-TA2-A3,
  RelativerPfad = Examen/46116/2018/09/Thema-2/Teilaufgabe-2/Aufgabe-3.tex,
  ZitatSchluessel = examen:46116:2018:09,
  BearbeitungsStand = mit Lösung,
  Korrektheit = korrekt und überprüft,
  Ueberprueft = {mit Dozentenlösung abgeglichen},
  Stichwoerter = {SQL, SQL mit Übungsdatenbank, CREATE TABLE, INSERT, ALTER TABLE, UPDATE, DELETE, VIEW, GROUP BY, DROP TABLE},
  EinzelpruefungsNr = 46116,
  Jahr = 2018,
  Monat = 09,
  ThemaNr = 2,
  TeilaufgabeNr = 2,
  AufgabeNr = 3,
}

\let\f=\textbf
\let\u=\underline
\let\s=\bSqlCode

Gegeben\index{SQL} \footcite{examen:46116:2018:09} sei das folgende
Datenbank-Schema, das für die Speicherung der Daten einer Schule
entworfen wurde, zusammen mit einem Teil seiner Ausprägung. Die
Primärschlüssel-Attribute sind jeweils unterstrichen.
\footcite{db:ab:3}

Die Relation \emph{Schüler} enthält allgemeine Daten zu den Schülerinnen
und Schülern. Schülerinnen und Schüler nehmen an Prüfungen in
verschiedenen Unterrichtsfächern teil und erhalten dadurch Noten. Diese
werden in der Relation \emph{Noten} abgespeichert. Prüfungen haben ein
unterschiedliches Gewicht. Beispielsweise hat ein mündliches Ausfragen
oder eine Extemporale das Gewicht $1$, während eine Schulaufgabe das
Gewicht $2$ hat.

\bPseudoUeberschrift{Schüler:}

\begin{center}
\begin{tabular}{|llll|}
\hline
\f{\u{SchülerID}} & \f{Vorname} & \f{Nachname}  & \f{Klasse} \\
1                 & Laura       & Müller        & 4A         \\
2                 & Linus       & Schmidt       & 4A         \\
3                 & Jonas       & Schneider     & 4A         \\
4                 & Liam        & Fischer       & 4B         \\
5                 & Tim         & Weber         & 4B         \\
6                 & Lea         & Becker        & 4B         \\
7                 & Emilia      & Klein         & 4C         \\
8                 & Julia       & Wolf          & 4C         \\
\hline
\end{tabular}
\end{center}

\bPseudoUeberschrift{Noten:}

\begin{center}
\begin{tabular}{|lllll|}
\hline
\f{\u{SchülerID{[}Schüler{]}}} & \f{Schulfach}  & \f{Note} & \f{Gewicht} & \f{Datum}  \\
1                              & Mathematik     & 3        & 2           & 23.09.2017 \\
1                              & Mathematik     & 1        & 1           & 03.10.2017 \\
1                              & Mathematik     & 2        & 2           & 15.10.2017 \\
1                              & Mathematik     & 4        & 1           & 11.11.2017 \\
\hline
\end{tabular}
\end{center}

\begin{bAdditum}[Übungsdatenbank]
% Datenbankname: schuldatenbank
\begin{minted}{sql}
CREATE TABLE Schüler (
  SchülerID INTEGER PRIMARY KEY NOT NULL,
  Vorname VARCHAR(20),
  Nachname VARCHAR(20),
  Klasse VARCHAR(5)
);

CREATE TABLE Noten (
  SchülerID INTEGER NOT NULL,
  Schulfach VARCHAR(20),
  Note INTEGER,
  Gewicht INTEGER,
  Datum DATE,
  PRIMARY KEY (SchülerID, Schulfach, Datum),
  FOREIGN KEY (SchülerID) REFERENCES Schüler(SchülerID)
);

INSERT INTO Schüler VALUES
  (1, 'Laura',  'Müller',    '4A'),
  (2, 'Linus',  'Schmidt',   '4A'),
  (3, 'Jonas',  'Schneider', '4A'),
  (4, 'Liam',   'Fischer',   '4B'),
  (5, 'Tim',    'Weber',     '4B'),
  (6, 'Lea',    'Becker',    '4B'),
  (7, 'Emilia', 'Klein',     '4C'),
  (8, 'Julia',  'Wolf',      '4C');

INSERT INTO Noten VALUES
  (1, 'Mathematik', 3, 2, '23.09.2017'),
  (1, 'Mathematik', 1, 1, '03.10.2017'),
  (1, 'Mathematik', 2, 2, '15.10.2017'),
  (1, 'Mathematik', 4, 1, '11.11.2017');
\end{minted}
\index{SQL mit Übungsdatenbank}
\end{bAdditum}

\begin{enumerate}

%%
% (a)
%%

\item Geben Sie die SQL-Befehle an, die notwendig sind, um die oben
dargestellten Tabellen in einer SQL-Datenbank anzulegen.
\index{CREATE TABLE}

\begin{bAntwort}
\begin{minted}{sql}
CREATE TABLE IF NOT EXISTS Schüler (
  SchülerID INTEGER PRIMARY KEY NOT NULL,
  Vorname VARCHAR(20),
  Nachname VARCHAR(20),
  Klasse VARCHAR(5)
);

CREATE TABLE IF NOT EXISTS Noten (
  SchülerID INTEGER NOT NULL,
  Schulfach VARCHAR(20),
  Note INTEGER,
  Gewicht INTEGER,
  Datum DATE,
  PRIMARY KEY (SchülerID, Schulfach, Datum),
  FOREIGN KEY (SchülerID) REFERENCES Schüler(SchülerID)
);
\end{minted}
\end{bAntwort}

%%
% (b)
%%

\item Entscheiden Sie jeweils, ob folgende Einfügeoperationen vom
gegebenen Datenbanksystem (mit der angegebenen Ausprägungen) erfolgreich
verarbeitet werden können und begründen Sie Ihre Antwort kurz.
\index{INSERT}

\begin{minted}{sql}
INSERT INTO Schüler
  (SchülerID, Vorname, Nachname, Klasse)
VALUES
  (6, 'Johannes', 'Schmied', '4C');
\end{minted}

\begin{bAntwort}
Nein. Ein/e Schüler/in mit der ID 6 existiert bereits. Primärschlüssel
müssen eindeutig sein.
\end{bAntwort}

\begin{minted}{sql}
INSERT INTO Noten VALUES (6, 'Chemie', 1, 2, '1.4.2020');
\end{minted}

\begin{bAntwort}
Nein. Ein \emph{Datum} ist zwingend notwendig. Da \emph{Datum} im
Primärschlüssel enthalten ist, darf es nicht NULL sein. Es gibt auch
keine/n Schüler/in mit der ID 9. Der/die Schüler/in  müsste vorher
angelegt werden, da die Spalte \emph{SchülerID} von der Tabelle
\emph{Noten} auf den Fremdschlüssel \emph{SchülerId} aus der
Schülertabelle verweist.
\end{bAntwort}

%%
% (c)
%%

\item Geben Sie die Befehle für die folgenden Aktionen in SQL an.
Beachten Sie dabei, dass die Befehle auch noch bei Änderungen des oben
gegebenen Datenbankzustandes korrekte Ergebnisse zurückliefern müssen.
\index{ALTER TABLE}

\begin{itemize}
\item Die Schule möchte verhindern, dass in die Datenbank mehrere Kinder
mit dem selben Vornamen in die gleiche Klasse kommen. Dies soll bereits
auf Datenbankebene verhindert werden. Dabei sollen die Primärschlüssel
nicht verändert werden. Geben Sie den Befehl an, der diese Änderung
durchführt.

\begin{bAntwort}
\begin{minted}{sql}
ALTER TABLE Schüler
ADD CONSTRAINT eindeutiger_Vorname UNIQUE (Vorname, Klasse);
\end{minted}
\end{bAntwort}

\item Der Schüler \emph{Tim Weber} (SchülerID: 5) wechselt die Klasse.
Geben Sie den SQL-Befehl an, der den genannten Schüler in die Klasse
\emph{„4C“} überführt.
\index{UPDATE}

\begin{bAntwort}
\begin{minted}{sql}
UPDATE Schüler
SET Klasse = '4C'
WHERE
  Vorname = 'Tim' AND
  Nachname = 'Weber' AND
  SchülerID = 5;
\end{minted}
\end{bAntwort}

\item Die Schülerin \emph{Laura Müller} (SchülerID: 1) zieht um und
wechselt die Schule. Löschen Sie die Schülerin aus der Datenbank. Nennen
Sie einen möglichen Effekt, welcher bei der Verwendung von Primär- und
Fremdschlüsseln auftreten kann.
\index{DELETE}

\begin{bAntwort}
Alle Noten von \emph{Laura Müller} werden gelöscht, falls \s{ON DELETE
CASCADE} gesetzt ist. Oder es müssen erst alle Fremdschlüsselverweise
auf diese \emph{SchülerID} in der Tabelle \emph{Noten} gelöscht werden

\begin{minted}{sql}
DELETE FROM Noten
WHERE SchülerID = 1;
\end{minted}
\end{bAntwort}

\item Erstellen Sie eine View \emph{„DurchschnittsNoten“}, die die
folgenden Spalten beinhaltet: \emph{Klasse}, \emph{Schulfach}, \emph{Durchschnittsnote}

Hinweis: Beachten Sie die Gewichte der Noten.
\index{VIEW}
\index{GROUP BY}

\begin{bAntwort}
\begin{minted}{sql}
CREATE VIEW DurchschnittsNoten AS (
  (SELECT s.Klasse, n.Schulfach, (SUM(n.Note * n.Gewicht) / SUM(n.Gewicht)) AS Durchschnittsnote
  FROM Noten n, Schüler s
  WHERE s.SchülerID = n.SchülerID
  GROUP BY s.Klasse, n.Schulfach)
);

SELECT * FROM DurchschnittsNoten;
\end{minted}

\begin{bSqlErgebnis}
 klasse | schulfach  | durchschnittsnote
--------+------------+-------------------
 4A     | Mathematik |                 2
(1 row)
\end{bSqlErgebnis}
\end{bAntwort}

\item Geben Sie den Befehl an, der die komplette Tabelle \emph{„Noten“}
löscht.
\index{DROP TABLE}

\begin{bAntwort}
\begin{minted}{sql}
DROP TABLE Noten;
\end{minted}
\end{bAntwort}

\end{itemize}

%%
% (d)
%%

\item Formulieren Sie die folgenden Anfragen in SQL. Beachten Sie dabei,
dass sie SQL-Befehle auch noch bei Änderungen der Ausprägung die
korrekten Anfrageergebnisse zurückgeben sollen.

\begin{itemize}

%%
%
%%

\item Gesucht ist die durchschnittliche Note, die im Fach Mathematik
vergeben wird.

Hinweis: Das Gewicht ist bei dieser Anfrage nicht relevant

\begin{bAntwort}
\begin{minted}{sql}
SELECT AVG(Note)
FROM Noten
WHERE Schulfach = 'Mathematik';
\end{minted}
\end{bAntwort}

%%
%
%%

\item Berechnen Sie die Anzahl der Schüler, die im Fach Mathematik am
23.09.2017 eine Schulaufgabe (\dh Gewicht=2) geschrieben haben.

\begin{bAntwort}
\begin{minted}{sql}
SELECT COUNT(*) AS Anzahl_Schüler
FROM Noten
WHERE Datum = '23.09.2017' AND Gewicht = 2 AND Schulfach = 'Mathematik';
\end{minted}

\begin{bSqlErgebnis}
 anzahl_schüler
----------------
              1
(1 row)
\end{bSqlErgebnis}
\end{bAntwort}

%%
%
%%

\item Geben Sie die \emph{SchülerID} aller Schüler zurück, die im Fach
Mathematik mindestens drei mal die Schulnote $6$ geschrieben haben.

\begin{bAntwort}
\begin{minted}{sql}
SELECT SchülerID
FROM Noten
WHERE Schulfach = 'Mathematik' AND Note = 6
GROUP BY SchülerID
HAVING COUNT(*) >= 3;
\end{minted}

\begin{bSqlErgebnis}
 schülerid
-----------
(0 rows)
\end{bSqlErgebnis}
\end{bAntwort}

%%
%
%%

\item Gesucht ist der Notendurchschnitt bezüglich jedes Fachs der Klasse
„4A“.

\begin{bAntwort}
\begin{minted}{sql}
SELECT n.Schulfach, AVG(n.Note)
FROM Schüler s, Noten n
WHERE s.SchülerID = n.SchülerID AND s.Klasse = '4A'
GROUP BY n.Schulfach;
\end{minted}

\begin{bSqlErgebnis}
schulfach  |        avg
------------+--------------------
 Mathematik | 2.5000000000000000
(1 row)
\end{bSqlErgebnis}
\end{bAntwort}
\end{itemize}

%%
% (e)
%%

\item Geben Sie jeweils an, welchen Ergebniswert die folgenden
SQL-Befehle für die gegebene Ausprägung zurückliefern.

\begin{minted}{sql}
SELECT COUNT(DISTINCT Klasse)
FROM
Schüler NATURAL JOIN Noten;
\end{minted}

\begin{bAntwort}
\begin{bSqlErgebnis}
 count
-------
     1
(1 row)
\end{bSqlErgebnis}
4A von Laura Müller. Ohne \s{DISTINCT} wäre das Ergebnis 4.
\end{bAntwort}

\begin{minted}{sql}
SELECT COUNT(ALL Klasse)
FROM
Noten, Schüler;
\end{minted}

\begin{bAntwort}
\begin{bSqlErgebnis}
 count
-------
    32
(1 row)
\end{bSqlErgebnis}
Es entsteht das Kreuzprodukt ($8 \cdot 4 = 32$).
\end{bAntwort}

\begin{minted}{sql}
SELECT COUNT(Note)
FROM
Schüler NATURAL LEFT OUTER JOIN Noten;
\end{minted}

\begin{bAntwort}
\begin{minted}{sql}
SELECT * FROM Schüler NATURAL LEFT OUTER JOIN Noten;
\end{minted}

ergibt:

\begin{bSqlErgebnis}
 schülerid | vorname | nachname  | klasse | schulfach  | note | gewicht |   datum
-----------+---------+-----------+--------+------------+------+---------+------------
         1 | Laura   | Müller    | 4A     | Mathematik |    3 |       2 | 2017-09-23
         1 | Laura   | Müller    | 4A     | Mathematik |    1 |       1 | 2017-10-03
         1 | Laura   | Müller    | 4A     | Mathematik |    2 |       2 | 2017-10-15
         1 | Laura   | Müller    | 4A     | Mathematik |    4 |       1 | 2017-11-11
         2 | Linus   | Schmidt   | 4A     |            |      |         |
         5 | Tim     | Weber     | 4B     |            |      |         |
         8 | Julia   | Wolf      | 4C     |            |      |         |
         6 | Lea     | Becker    | 4B     |            |      |         |
         4 | Liam    | Fischer   | 4B     |            |      |         |
         3 | Jonas   | Schneider | 4A     |            |      |         |
         7 | Emilia  | Klein     | 4C     |            |      |         |
(11 rows)
\end{bSqlErgebnis}

\begin{bSqlErgebnis}
 count
-------
     4
(1 row)
\end{bSqlErgebnis}

\s{COUNT} zählt die \s{NULL}-Werte nicht mit. Die \emph{Laura Müller}
hat 4
Noten.
\end{bAntwort}

\begin{minted}{sql}
SELECT COUNT(*)
FROM
Schüler NATURAL LEFT OUTER JOIN Noten;
\end{minted}

\begin{bAntwort}
\begin{bSqlErgebnis}
 count
-------
    11
(1 row)
\end{bSqlErgebnis}
Siehe Zwischenergebistabelle in der obenstehenden Antwort. Alle Schüler
und die Laura 4-mal, weil sie 4 Noten hat.
\end{bAntwort}
\end{enumerate}
\end{document}
