\documentclass{bschlangaul-aufgabe}
\bLadePakete{syntax,rmodell}
\begin{document}
\bAufgabenMetadaten{
  Titel = {Aufgabe 1: SQL},
  Thematik = {Personalverwaltung},
  Referenz = 66116-2016-H.T1-TA1-A4,
  RelativerPfad = Examen/66116/2016/09/Thema-1/Teilaufgabe-1/Aufgabe-4.tex,
  ZitatSchluessel = examen:66116:2016:09,
  BearbeitungsStand = mit Lösung,
  Korrektheit = unbekannt,
  Ueberprueft = {unbekannt},
  Stichwoerter = {SQL, SQL mit Übungsdatenbank, VIEW, WITH, DELETE},
  EinzelpruefungsNr = 66116,
  Jahr = 2016,
  Monat = 09,
  ThemaNr = 1,
  TeilaufgabeNr = 1,
  AufgabeNr = 4,
}

Gegeben\index{SQL}
\footcite{examen:66116:2016:09} sind folgende Relationen aus einer Personalverwaltung:
\footcite[Aufgabe 1]{db:pu:3}

\begin{bRelationenModell}
\bRelationMenge{Mitarbeiter}{
\bPrimaer{MitarbeiterID}, Vorname, Nachname, \bFremd{Vorgesetzter[Mitarbeiter]}, \bFremd{AbteilungsID[Abteilung]}, Telefonnummer, Gehalt}

\bRelationMenge{Abteilung}{\bPrimaer{AbteilungsID}, Bezeichnung}
\end{bRelationenModell}

\begin{bAdditum}[Übungsdatenbank]
% Datenbankname: Personalverwaltung
\begin{minted}{sql}
CREATE TABLE Abteilung(
  AbteilungsID INTEGER PRIMARY KEY,
  Bezeichnung VARCHAR(30)
);

CREATE TABLE Mitarbeiter(
  MitarbeiterID INTEGER PRIMARY KEY,
  Vorname VARCHAR(30),
  Nachname VARCHAR(30),
  Vorgesetzter INTEGER REFERENCES Mitarbeiter(MitarbeiterID),
  AbteilungsID INTEGER REFERENCES Abteilung(AbteilungsID),
  Telefonnummer VARCHAR(50),
  Gehalt DOUBLE PRECISION
);

INSERT INTO Abteilung VALUES
  (1,  'Buchhaltung'),
  (2,  'Vertrieb'),
  (42, 'Managment'),
  (4,  'Qualitätskontrolle'),
  (5,  'Produktion');

INSERT INTO Mitarbeiter
  (MitarbeiterID, Vorname, Nachname, Vorgesetzter, AbteilungsID, Telefonnummer, Gehalt)
VALUES
  (1,  'Hans',   'Meier',    11,   4, '023/13432', 2335),
  (2,  'Fred',   'Wolitz',   11,   2, '0233/413432', 1233),
  (11, 'Lea',    'Müller',   NULL, 42, '0343/3452', 5875),
  (3,  'Till',   'Fuchs',    2,    1, '023/13344', 2345),
  (4,  'Fred',   'Hase',     11,   4, '04/453432', 1334),
  (12, 'Gerd',   'Navratil', NULL, 42, '0345/552', 7154),
  (6,  'Jürgen', 'Schmidt',  12,   5, '097/dfg854', 654);
\end{minted}
\index{SQL mit Übungsdatenbank}
\end{bAdditum}
\begin{enumerate}

%%
% (a)
%%

\item Schreiben Sie eine SQL-Anfrage, die \emph{Vor-} und
\emph{Nachnamen} der \emph{Mitarbeiter} aller \emph{Abteilungen} mit der
Bezeichnung \emph{„Buchhaltung“} ausgibt, absteigend sortiert nach
\emph{Mitarbeiter-ID}.

\begin{bAntwort}
\begin{minted}{sql}
SELECT Vorname, Nachname
FROM Mitarbeiter m, Abteilung a
WHERE
  m.AbteilungsID = a.AbteilungsID AND
  a.Bezeichnung = 'Buchhaltung'
ORDER BY m.MitarbeiterID DESC;
\end{minted}

\begin{verbatim}
 vorname | nachname
---------+----------
 Till    | Fuchs
 Hans    | Meier
(2 rows)
\end{verbatim}
\end{bAntwort}

%%
% (b)
%%

\item Schreiben Sie eine SQL-Anfrage, die die Nachnamen aller
Mitarbeiter mit dem Nachnamen ihres jeweiligen direkten Vorgesetzten
ausgibt. Mitarbeiter ohne Vorgesetzten sollen in der Ausgabe ebenfalls
enthalten sein. In diesem Fall soll der Nachname des Vorgesetzten NULL
sein.

\begin{bAntwort}
\begin{minted}{sql}
SELECT m.Nachname AS Mitarbeiter, v.Nachname AS Vorgesetzter
FROM Mitarbeiter m LEFT OUTER JOIN Mitarbeiter v
ON m.Vorgesetzter = v.MitarbeiterID;
\end{minted}

\begin{verbatim}
 mitarbeiter | vorgesetzter
-------------+--------------
 Meier       | Müller
 Wolitz      | Müller
 Müller      |
 Fuchs       | Wolitz
 Hase        | Müller
 Navratil    |
 Schmidt     | Navratil
(7 rows)
\end{verbatim}
\end{bAntwort}

%%
% (c)
%%

\item Schreiben Sie eine SQL-Anfrage, die die 10 Abteilungen ausgibt,
deren Mitarbeiter das höchste Durchschnittsgehalt haben. Ausgegeben
werden sollen der Rang (1 = höchstes Durchschnittsgehalt bis 10 =
niedrigstes Durchschnittsgehalt), die Bezeichnung sowie das
Durchschnittsgehalt der Abteilung. Gehen Sie davon dass es keine zwei
Abteilungen mit gleichem Durchschnittsgehalt gibt. Sie können der
Übersichtlichkeit halber Views oder With-Anweisungen verwenden.
Verwenden Sie jedoch keine datenbanksystemspezifischen Erweiterungen wie
\verb|limit| oder \verb|rownum|.\index{VIEW}\index{WITH}

\begin{bAntwort}
\begin{minted}{sql}
CREATE VIEW Durchschnittsgehälter AS
SELECT Abteilung.AbteilungsID, Bezeichnung,
  AVG (Gehalt) AS Durchschnittsgehalt
FROM Mitarbeiter, Abteilung
WHERE Mitarbeiter.AbteilungsID = Abteilung.AbteilungsID
GROUP BY Abteilung.AbteilungsID, Bezeichnung;

SELECT a.Bezeichnung, a.Durchschnittsgehalt, COUNT (*) AS Rang
FROM Durchschnittsgehälter a, Durchschnittsgehälter b
WHERE a.Durchschnittsgehalt <= b.Durchschnittsgehalt
GROUP BY a.AbteilungsID, a.Bezeichnung, a.Durchschnittsgehalt
HAVING COUNT(*) <= 10
ORDER BY Rang ASC;
\end{minted}

\begin{verbatim}
 bezeichnung | durchschnittsgehalt | rang
-------------+---------------------+------
 Managment   |              6514.5 |    1
 Buchhaltung |                2340 |    2
 Vertrieb    |              1283.5 |    3
 Produktion  |                 654 |    4
(4 rows)
\end{verbatim}
\end{bAntwort}

%%
% (d)
%%

\item Schreiben Sie eine SQL-Anfrage, die das Gehalt aller Mitarbeiter
aus der Abteilung mit der AbteilungsID 42 um 5\% erhöht.

\begin{bAntwort}
\begin{verbatim}
 vorname | nachname | gehalt
---------+----------+--------
 Lea     | Müller   |   5875
 Gerd    | Navratil |   7154
(2 rows)
\end{verbatim}

\begin{minted}{sql}
SELECT Vorname, Nachname, Gehalt
FROM MITARBEITER
WHERE AbteilungsId = 42
ORDER BY Gehalt;

UPDATE Mitarbeiter
SET Gehalt = 1.05 * Gehalt
WHERE AbteilungsID = 42;

SELECT Vorname, Nachname, Gehalt
FROM MITARBEITER
WHERE AbteilungsId = 42
ORDER BY Gehalt;
\end{minted}

\begin{verbatim}
 vorname | nachname |      gehalt
---------+----------+-------------------
 Lea     | Müller   |           6168.75
 Gerd    | Navratil | 7511.700000000001
(2 rows)
\end{verbatim}
\end{bAntwort}

%%
% (e)
%%

\item Alle \emph{Abteilungen} mit Bezeichnung
\emph{„Qualitätskontrolle“} sollen zusammen mit den Datensätzen ihrer
\emph{Mitarbeiter} gelöscht
werden. \verb|ON DELETE CASCADE| ist für keine der Tabellen gesetzt.
Schreiben Sie die zum Löschen notwendigen SQL-Anfragen.\index{DELETE}

\begin{bAntwort}
\begin{verbatim}
 vorname | nachname
---------+----------
 Hans    | Meier
 Fred    | Wolitz
 Lea     | Müller
 Till    | Fuchs
 Fred    | Hase
 Gerd    | Navratil
 Jürgen  | Schmidt
(7 rows)

 abteilungsid |    bezeichnung
--------------+--------------------
            1 | Buchhaltung
            2 | Vertrieb
           42 | Managment
            4 | Qualitätskontrolle
            5 | Produktion
(5 rows)
\end{verbatim}

\begin{minted}{sql}
SELECT Vorname, Nachname FROM Mitarbeiter;
SELECT * FROM Abteilung;

DELETE FROM Mitarbeiter
WHERE AbteilungsID IN (
  SELECT a.AbteilungsID
  FROM Abteilung a
  WHERE a.Bezeichnung = 'Qualitätskontrolle'
);

DELETE FROM Abteilung
WHERE Bezeichnung = 'Qualitätskontrolle';

SELECT Vorname, Nachname FROM Mitarbeiter;
SELECT * FROM Abteilung;
\end{minted}

\begin{verbatim}
 vorname | nachname
---------+----------
 Fred    | Wolitz
 Lea     | Müller
 Till    | Fuchs
 Gerd    | Navratil
 Jürgen  | Schmidt
(5 rows)

 abteilungsid | bezeichnung
--------------+-------------
            1 | Buchhaltung
            2 | Vertrieb
           42 | Managment
            5 | Produktion
(4 rows)
\end{verbatim}
\end{bAntwort}

%%
% (f)
%%

\item Alle Mitarbeiter sollen mit SQL-Anfragen nach den Telefonnummern
anderer Mitarbeiter suchen können. Sie dürfen jedoch das Gehalt der
Mitarbeiter nicht sehen können. Erläutern Sie in zwei bis drei Sätzen
eine Möglichkeit, wie dies in einem Datenbanksystem realisiert werden
kann, ohne die gegebenen Relationen, die Tabellen als abgelegt sind, zu
verändern. Sie brauchen hierzu keinen SQL-Code schreiben.

\begin{bAntwort}
Wir könnten eine VIEW erstellen, die zwar Namen und ID der anderen
Mitarbeiter, sowie ihre Telefonnummern enthält (evtl. auch
Abteilungsbezeichnung und ID), aber eben nicht das Gehalt: Mitarbeiter
arbeiten auf eingeschränkter Sicht.

Alternativ mit \verb|GRANT|:

explizit mit \verb|SELECT| die Spalten auswählen,
die man lesen können soll (auf nicht angegebene Spalten ist kein Zugriff
möglich)

% SELECT rolname FROM pg_roles;
\begin{minted}{sql}
GRANT SELECT (Vorname, Nachname, Telefonnummer)
ON Mitarbeiter TO postgres;
\end{minted}
\end{bAntwort}
\end{enumerate}

\end{document}
