\documentclass{bschlangaul-aufgabe} \bLadePakete{syntax} \begin{document} \bAufgabenMetadaten{ Titel = {Aufgabe 5: SQL}, Thematik = {Mitarbeiterverwaltung}, Referenz = 66113-2003-F.T1-A5, RelativerPfad = Examen/66113/2003/03/Thema-1/Aufgabe-5.tex, ZitatSchluessel = 66113:2003:03, ZitatBeschreibung = {Thema 1 Aufgabe 5}, BearbeitungsStand = mit Lösung, Korrektheit = unbekannt, Ueberprueft = {unbekannt}, Stichwoerter = {SQL, SQL mit Übungsdatenbank}, EinzelpruefungsNr = 66113, Jahr = 2003, Monat = 03, ThemaNr = 1, AufgabeNr = 5, } Gegeben\index{SQL} \footcite[Thema 1 Aufgabe 5]{66113:2003:03} seien die folgenden drei Relationen. Diese Relationen erfassen die Mitarbeiterverwaltung eines Unternehmens. Schlüssel sind fett dargestellt und Fremdschlüssel sind kursiv dargestellt. So werden Mitarbeiter, Abteilungen und Unternehmen jeweils durch ihre Nummer identifiziert. AbtNr ist die Nummer der Abteilung, in der ein Mitarbeiter arbeitet. Manager ist die Nummer des Mitarbeiters, der die Abteilung leitet. \verb|UntNr| ist die Nummer des Unternehmens, dem eine Abteilung zugeordnet ist. \footcite[Aufgabe 2: SQL]{db:pu:2} \begin{minted}{md} Mitarbeiter(Nummer, Name, Alter, Gehalt, AbtNr) Abteilung(Nummer, Name, Budget, Manager, UntNr) Unternehmen(Nummer, Name, Adresse) \end{minted} % Datenbankname: mitarbeiterverwaltung \begin{minted}{sql} CREATE TABLE unternehmen ( Nummer integer NOT NULL PRIMARY KEY, Name VARCHAR(20) DEFAULT NULL, Adresse VARCHAR(50) DEFAULT NULL ); CREATE TABLE abteilung ( Nummer integer NOT NULL PRIMARY KEY, Name VARCHAR(20) DEFAULT NULL, Budget float DEFAULT NULL, Manager VARCHAR(20) NOT NULL, UntNr integer DEFAULT NULL REFERENCES unternehmen (Nummer) ); CREATE TABLE mitarbeiter ( Nummer integer NOT NULL PRIMARY KEY, Name VARCHAR(20) NOT NULL, Alter integer NOT NULL, Gehalt float NOT NULL, AbtNr integer NOT NULL REFERENCES abteilung (Nummer) ); INSERT INTO unternehmen (Nummer, Name, Adresse) VALUES (1, 'Test.com', 'Alter Hafen 11'), (2, 'Party.de', 'Technostraße 3'), (3, 'IT.ch', 'Sequelweg 1'); INSERT INTO abteilung (Nummer, Name, Budget, Manager, UntNr) VALUES (1, 'Personal_Care', 20000, 'Huber', 1), (11, 'Tequilla_Mix', 50000, 'Taylor', 2), (21, 'Nerds', 500, 'Gates', 3); INSERT INTO mitarbeiter (Nummer, Name, Alter, Gehalt, AbtNr) VALUES (1, 'Müller', 30, 30000, 1), (2, 'Huber', 45, 80000, 1), (3, 'Habermeier', 62, 40000, 1), (4, 'Leifsson', 27, 50000, 1), (5, 'Taylor', 37, 85000, 11), (6, 'Smith', 61, 34000, 11), (7, 'Pitt', 36, 40000, 11), (8, 'Thompson', 54, 52000, 11), (9, 'Gates', 69, 15000000, 21), (10, 'Zuckerberg', 36, 10000000, 21), (11, 'Jobs', 99, 14000000, 21), (12, 'Nakamoto', 66, 5000000, 21); \end{minted} \index{SQL mit Übungsdatenbank} \begin{enumerate} % a) \item Wie hoch ist das Durchschnittsalter der Abteilung „Personal Care“ im Unternehmen „Test.com“? \begin{bAntwort} \verb|GROUP BY| nicht nötig, \verb|AS| nicht vergessen. \begin{minted}{sql} SELECT AVG(m.Alter) AS Durchschnittsalter FROM Unternehmen u, Abteilung a, Mitarbeiter m WHERE a.Name = 'Personal Care' AND u.Name = 'Test.com' AND u.Nummer = a.UntNr AND m.AbtNr = a.Nummer; \end{minted} \end{bAntwort} %% % b) %% \item Geben Sie für jedes Unternehmen das Durchschnittsalter der Mitarbeiter an! \begin{bAntwort} Statt \verb|a.UntNr| kann \verb|u.Nummer| verwendet werden. \verb|a.UntNr| nur deshalb, weil man dann eventuell den Join über die Unternehmenstabelle sparen kann. Alles was ausgegeben werden soll, muss auch in \verb|GROUP BY| enthalten sein. \begin{minted}{sql} SELECT a.UntNr, u.Name, AVG(m.Alter) as Durchschnittsalter FROM Unternehmen u, Abteilung a, Mitarbeiter m WHERE u.Nummer = a.UntNr AND m.AbtNr = a.Nummer GROUP BY a.UntNr, u.Name; \end{minted} \end{bAntwort} %% % c) %% \item Wie viele Mitarbeiter im Unternehmen „Test.com“ sind älter als ihr Chef? (D.h. sind älter als der Manager der Abteilung, in der sie arbeiten.) \begin{bAntwort} \begin{minted}{sql} SELECT COUNT(*) FROM Mitarbeiter m, Abteilung a, Unternehmen u WHERE m.AbtNr = a.Nummer AND a.UntNr = u.Nummer AND u.Name = 'Test.com' AND m.Alter > ( SELECT ma.Alter FROM Mitarbeiter ma, Abteilung ab WHERE ma.Nummer = ab.Manager AND a.Nummer = ab.Nummer ); \end{minted} oder einfacher: \begin{minted}{sql} SELECT COUNT(*) FROM Mitarbeiter m, Abteilung a, Unternehmen u WHERE m.AbtNr = a.Nummer AND a.UntNr = u.Nummer AND u.Name = 'Test.com' AND m.Alter > ( SELECT ma.Alter FROM Mitarbeiter ma WHERE ma.Nummer = a.Manager ); \end{minted} Alternativ Lösung ohne Unterabfragem, mit Self join: \begin{minted}{sql} SELECT COUNT(*) FROM Mitarbeiter m, Abteilung a, Unternehmen u, Mitarbeiter m2 WHERE m.AbtNr = a.Nummer AND a.UntNr = u.Nummer AND u.Name = 'Test.com' AND a.Manager = m2.Nummer AND m.Alter > m2.Atler; \end{minted} \end{bAntwort} %% % (d) %% \item Welche Abteilungen haben ein geringeres Budget als die Summe der Gehälter der Mitarbeiter, die in der Abteilung arbeiten? \begin{bAntwort} \begin{minted}{sql} SELECT a.Name, a.Nummer FROM Abteilung a WHERE a.Budget < ( SELECT SUM(m.Gehalt) FROM Mitarbeiter m WHERE a.Nummer = m.AbtNr ); \end{minted} Ohne Unterabfrage \begin{minted}{sql} SELECT a.Name, a.Nummer FROM Abteilung a, Mitarbeiter m WHERE a.Nummer = m.AbtNr GROUP BY a.Nummer, a.Name, a.Budget HAVING a.Budget < SUM(m.Gehalt); \end{minted} \end{bAntwort} %% % (e) %% \item Versetzen Sie den Mitarbeiter „Wagner“ in die Abteilung „Personal Care“! \begin{bAntwort} \begin{minted}{sql} UPDATE Mitarbeiter m SET AbtNr = ( SELECT a.Nummer FROM Abteilung a WHERE a.Name = 'Personal Care' ) WHERE m.Name = 'Wagner'; \end{minted} \end{bAntwort} %% % (f) %% \item Löschen Sie die Abteilung „Personal Care“ mit allen ihren Mitarbeitern! \begin{bAntwort} \begin{minted}{sql} DELETE FROM Mitarbeiter WHERE AbtNr = ( SELECT a.Nummer FROM Abteilung a WHERE a.Name = 'Personal Care' ); DELETE FROM Abteilung WHERE Name = 'Personal Care'; \end{minted} \end{bAntwort} %% % (g) %% \item Geben Sie den Managern aller Abteilungen, die ihr Budget nicht überziehen, eine 10 Prozent Gehaltserhöhung. (Das Budget ist überzogen, wenn die Gehälter der Mitarbeiter höher sind als das Budget der Abteilung.) Zusatzfrage: Was passiert mit Mitarbeitern, die Manager von mehreren Abteilungen sind? \begin{bAntwort} \begin{minted}{sql} CREATE VIEW LowBudget AS ( SELECT Nummer FROM Abteilung WHERE Nummer NOT IN ( SELECT a.Nummer FROM Abteilung a WHERE a.Budget < ( SELECT SUM(Gehalt) FROM Mitarbeiter m Abteilung A WHERE m.AbtNr = A.Nummer AND a.Nummer = A.Nummer ) ) ) UPDATE Mitarbeiter SET Gehalt = 1.1 * Gehalt WHERE Nummer IN ( SELECT Manager FROM LowBudget, Abteilung WHERE LowBudget.Manager = Abteilung.Nummer ) \end{minted} \end{bAntwort} \end{enumerate} \end{document}