SQL-Übungsaufgaben zu JOINs, Aggregation, Unterabfragen und Transaktionen

https://bildung.social/@oerinformatik/112633708392604185

https://oer-informatik.de/sql-uebungsaufgaben

tl/dr; (ca. 60 min Bearbeitungszeit): Am Beispiel einer Rechnungsdatenbank sollen SQL-Befehle mit Unterabfragen, Aggregationen, Joins und Transaktionen erstellt werden. Die Lösungen und Erläuterungen können eingeblendet werden. (Zuletzt geändert am 17.06.2024)

Übungsaufgabe Rechnungsdatenbank:

Gegeben ist das folgende Datenmodell:

Relationenmodell für Rechnungen, Artikel, Rechnungspositionen und Adressen
Relationenmodell für Rechnungen, Artikel, Rechnungspositionen und Adressen

1a) Selektion und Projektion (8 Punkte)

Erstelle eine Abfrage, die alle RechnungsNr des Kunden mit dem Namen “Fantasie GmbH” ausgibt.

Beispielausgabe:

Name RechnungsNr
Fantasie GmbH 12345
Fantasie GmbH 56789
Fantasie GmbH 36789

1b) Aggregieren (8 Punkte)

Erstelle eine Abfrage, die alle RechnungsNr ausgibt sowie, falls vorhanden, die jeweiligen Rechnungssummen (die Summe der zugehörigen GesamtpreisNetto, ohne Berücksichtigung der Rabatte).

Beispielausgabe:

RechnungsNr Rechnungssumme
12345 123,45
56789 2343,34
23223 NULL
36789 145,45

Es ist lediglich ein Aggregat (Summe) und eine Gruppierung nötig:

Häufig werden bei dieser Aufgabe ohne Not mehrere Tabellen verknüpft, aber alle nötigen Attribute sind bereits in Rechnungsposition enthalten! Daher ist folgende Lösung zwar korrekt, aber unnötig kompliziert (und daher weniger performant):

1c) Bedingtes Aggregieren (8 Punkte)

Erstellen Sie eine Abfrage, die Rechnungsnummer und Anzahl der zugehörigen Rechnungspositionen aller Rechnungen ausgibt, die mehr als 20 Rechnungspositionen haben. Die Liste soll nach Anzahl der Positionen absteigend sortiert sein.

Beispielausgabe:

RechnungsNr AnzahlPosition
12345 321
56789 200
36789 15

Analog zur vorigen Aufgabe: alle nötigen Felder sind bereits in Rechnungsposition enthalten. Wichtig zur Reihenfolge der SQL-Befehle:

  • Sie werden in der Reihenfolge des Merksatzes “Warum geht Herbert oft laufen?” notiert (WHERE... GROUP... HAVING... ORDER BY... LIMIT...). Das gilt für MySQL/MariaDB.

  • Sie werden in der Reihenfolge des Merksatzes “Für wen geht Herbert so oft laufen?” ausgeführt (FROM... WHERE... GROUP... HAVING... SELECT... ORDER BY... LIMIT...). Auch das gilt für MySQL/MariaDB.

Daher ist der Alias AnzahlPosition des folgenden Befehls im HAVING-Clause noch nicht bekannt (dort muss COUNT(...) genutzt werden), aber im ORDER-Clause kann er genutzt werden (weil dieser nach SELECT ausgeführt wird).

Eine Verknüpfung mit Rechnung verkompliziert die Lösung unnötig und ist weniger performant.

1d) Abfragen aus mehreren Tabellen (12 Punkte)

Erstelle eine Abfrage, die Kundennummern und Namen aller Kunden ausgibt, die Rechnungen mit mehr als 20 Rechnungspositionen haben. Alle Kunden sollen darin höchstens einmal vorkommen.

Beispielausgabe:

Kundennummer Name
3456 Fantasie GmbH
78987 Beispiel AG
671235 Muster KG

Hier gibt es (mindestens) zwei unterschiedliche Strategien: über JOIN alle Tabellen zusammentragen, Datensätze Selektieren (HAVING) und die Ergebnismenge mit DISTINCT auf Unikate begrenzen oder die Selektion in einer Unterabfrage erledigen (was ich persönlich für eleganter halte):

Variante 1: Unterabfrage zur Datensatz-Selektion

Variante 2: Erst per JOIN maximale Information sammeln, die dann per HAVING und DISTINCT wieder eindampfen:

Es spielt hier keine Rolle, ob LEFT JOIN oder INNER JOIN verwendet wird, da ohnehin abgefragt wird, ob Rechnungspositionen vorhanden sind.

2a) Unterabfragen mit “vor jeder…” (8 Punkte)

Erstelle eine Abfrage, die alle Rechnungsnummern ausgibt, deren Rechnung (nach numerischen Rechnungsnummern sortiert) vor jeder Rechnung der Fantasie GmbH liegt.

Beispielausgabe:

RechnungsNr
12345

Eigentlich bedeutet ja “nach numerischen Rechnungsnummern sortiert”, dass es eindeutig um die Nummern geht… das wäre dann so:

… wer es jedoch falsch verstanden hat, der hat das “vor jeder Rechnung…” als eine zeitliche Bedingung gelesen und den Sortierungs-Teil am Ende eingebaut:

2b) Unterabfragen mit “vor einer…” (8 Punkte)

Erstelle eine Abfrage, die Rechnungsnummern ausgibt, deren Rechnung (nach numerischen Rechnungsnummern sortiert) vor irgendeiner Rechnung der Fantasie GmbH liegt.

RechnungsNr
67846
56789
36789

Analog zur vorigen Aufgabe:

… bei falsch verstandener Bedingung (Teilpunkte)

3a) Transaktionen starten (8 Punkte)

Es soll in einem sicheren Transaktions-Umfeld Veränderungen an der Datenbank vorgenommen werden, die sich noch nicht unmittelbar auswirken.

Erstelle alle Befehle, die nötig sind, um eine Transaktion zu starten und die (vorhandene) Rechnung „1234“ dem (vorhandenen) Kunden mit den KundenNr „234“ zuzuweisen.

3b) Transaktionen abbrechen (2 Punkte)

Mit welchem Befehl werden die Befehle aus Aufgabe a nicht zur Anwendung gebracht und die Transaktion abgebrochen?

3c) Transaktionen abschließen (2 Punkte)

Mit welchem Befehl werden die Befehle aus Aufgabe a persistent ausgeführt und die Transaktion abgeschlossen?


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: SQL-Übungsaufgaben zu JOINs, Aggregation, Unterabfragen und Transaktionen” von H. Stein (oer-informatik.de), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/sql-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/db-sql/dml-select-queries. Stand: 17.06.2024.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: