info:sek-ii:q2:sql:lektion3
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Vorhergehende Überarbeitung | |||
— | info:sek-ii:q2:sql:lektion3 [2024-02-18 11:41] (aktuell) – [BetterBox#40] christian.weber | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Aggregatsfunktionen und Gruppierungen ====== | ||
+ | |||
+ | < | ||
+ | <info w1|**Aggregatsfunktionen**((Quelle der Texte: https:// | ||
+ | |||
+ | Mit den Aggregatfunktionen werden statistische Auswertungen numerischer Daten in einer Datenbank vorgenommen. Jede Aggregatfunktion wird auf ein Attribut einer Tabelle angewendet und liefert als Ergebnis einen Zahlenwert zurück. Mit deren Hilfe kann man z.B. die Anzahl an Datensätzen ermitteln oder die Summe, das Maximum/ | ||
+ | |||
+ | </ | ||
+ | < | ||
+ | |||
+ | Die Anzahl aller Datensätze einer Tabelle zählt man mit '' | ||
+ | |||
+ | <code sql> | ||
+ | SELECT COUNT(*) AS AnzahlBestellungen | ||
+ | FROM Orders; | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | |||
+ | <code sql> | ||
+ | SELECT COUNT(ShippedDate) AS Versendete | ||
+ | FROM Orders; | ||
+ | </ | ||
+ | |||
+ | <code sql> | ||
+ | SELECT COUNT(*) - COUNT(ShippedDate) AS NichtVersendete | ||
+ | FROM Orders; | ||
+ | </ | ||
+ | |||
+ | Will man nur die verschiedenen Werte einer Spalte zählen, so benutzt man '' | ||
+ | |||
+ | <code sql> | ||
+ | SELECT COUNT(DISTINCT ShipCountry) AS AnzahlLänder | ||
+ | FROM Orders; | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | |||
+ | Der '' | ||
+ | |||
+ | <code sql> | ||
+ | SELECT SUM(unitsInStock) AS AnzahlProdukte | ||
+ | FROM Products; | ||
+ | </ | ||
+ | |||
+ | <code sql> | ||
+ | SELECT | ||
+ | SUM(UnitsInStock) AS LagerbestandMorgens, | ||
+ | SUM(UnitsOnOrder) AS BestellteProdukte, | ||
+ | SUM(UnitsInStock) - SUM(UnitsOnOrder) AS LagerbestandAbends | ||
+ | FROM | ||
+ | Products; | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | |||
+ | Benutzt man diese Befehle, so erhält man die größte/ | ||
+ | |||
+ | <code sql> | ||
+ | SELECT MIN(unitPrice) AS KleinsterPreis | ||
+ | FROM Products; | ||
+ | </ | ||
+ | <code sql> | ||
+ | SELECT MAX(unitPrice) AS GrößterPreis | ||
+ | FROM Products; | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | |||
+ | '' | ||
+ | |||
+ | <code sql> | ||
+ | SELECT AVG(unitPrice) AS DurchschnittsPreis | ||
+ | FROM Products; | ||
+ | </ | ||
+ | |||
+ | Dabei werden alle Einträge addiert und dann durch die Anzahl der Einträge geteilt. Das könnten wir aber auch mit den bisher bereits bekannten Aggregatsfunktionen ermitteln: | ||
+ | |||
+ | <code sql> | ||
+ | SELECT SUM(unitPrice) / COUNT(unitPrice) AS DurchschnittsPreis | ||
+ | FROM Products; | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | |||
+ | Ohne Gruppierungen (die kommen gleich noch) kann man Aggregatsfunktionen nicht sinnvoll mit der Auswahl anderer Spalten mischen. In den meisten Datenbanksystemen kommt es dann zu einem Fehler. SQLite lässt solche Abfragen zu, allerdings ergeben die Ergebnisse dann nur wenig sinn. | ||
+ | |||
+ | Möchte man zum Beispiel wissen, welcher Lieferant die meisten Produkte im Lager hat, könnte man diese Abfrage erstellen. Diese liefert allerdings (offensichtlich) nicht das gewünschte Ergebnis. | ||
+ | |||
+ | < | ||
+ | <bbox w2> | ||
+ | <code sql> | ||
+ | SELECT SupplierID, SUM(UnitsInStock) | ||
+ | FROM Products; | ||
+ | </ | ||
+ | </ | ||
+ | <bbox w2> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | 3119 Produkte waren insgesamt im Lager, schaut man sich die gesamte Tabelle an, fällt (durch manuelles Nachzählen) auf, dass der Lieferant mit der SupplierID 1 nur 69 Produkte im Lager hat. | ||
+ | |||
+ | Wer mehr wissen möchte, kann diesen [[https:// | ||
+ | |||
+ | </ | ||
+ | <aufgabe w1|**Aufgabe 1**> | ||
+ | |||
+ | Nutze die [[https:// | ||
+ | |||
+ | * Wie viele Länder enthält die cia-Datenbank? | ||
+ | * Ermittle die Weltbevölkerung. | ||
+ | * Gib das Durchschnitts-Bruttoinlandsprodukt an. | ||
+ | * Wie groß sind Bevölkerung und Bruttoinlandsprodukt für ganz Europa? | ||
+ | * Ermittle die Flächen des kleinsten und größten Landes. | ||
+ | * Wie viele Regionen gibt es? | ||
+ | |||
+ | </ | ||
+ | <lösung w1 collapsed center|Lösungen zu Aufgabe 1> | ||
+ | <tabbox a)> | ||
+ | <code sql> | ||
+ | <tabbox b)> | ||
+ | <code sql> | ||
+ | <tabbox c)> | ||
+ | <code sql> | ||
+ | <tabbox d)> | ||
+ | <code sql> | ||
+ | <tabbox e)> | ||
+ | <code sql> | ||
+ | <tabbox f)> | ||
+ | <code sql> | ||
+ | </ | ||
+ | </ | ||
+ | <info w1|**Gruppierungen** ((Quelle der Texte: https:// | ||
+ | |||
+ | Mit der '' | ||
+ | |||
+ | </ | ||
+ | < | ||
+ | |||
+ | Wir können die Datensätze der [[https:// | ||
+ | |||
+ | < | ||
+ | <bbox w2> | ||
+ | <code sql> | ||
+ | SELECT Region | ||
+ | FROM cia | ||
+ | GROUP BY Region | ||
+ | </ | ||
+ | </ | ||
+ | <bbox w2> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Das obige Beispiel ist untypisch, weil man das Ergebnis einfacher auch so erhält: | ||
+ | |||
+ | <code sql> | ||
+ | SELECT DISTINCT Region | ||
+ | FROM cia | ||
+ | </ | ||
+ | |||
+ | Der Mehrwert der '' | ||
+ | |||
+ | < | ||
+ | <bbox w2> | ||
+ | <code sql> | ||
+ | SELECT Region, SUM(Einwohner), | ||
+ | FROM cia | ||
+ | GROUP BY Region | ||
+ | </ | ||
+ | </ | ||
+ | <bbox w2> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | < | ||
+ | |||
+ | Der typische Fehler im Zusammenhang mit der Gruppierung besteht darin, dass nach der Gruppenbildung noch versucht wird, Informationen von einzelnen Datensätzen auszugeben. Zum Beispiel: | ||
+ | |||
+ | < | ||
+ | <bbox w2> | ||
+ | <code sql> | ||
+ | SELECT Region, Name, SUM(Einwohner), | ||
+ | FROM cia | ||
+ | GROUP BY Region | ||
+ | </ | ||
+ | </ | ||
+ | <bbox w2> | ||
+ | {{ info: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Man kann zwar für jede Gruppe die Region und die Summe der Einwohner angeben, aber nicht den Namen, denn der ist für jedes Land einer Region anders. | ||
+ | |||
+ | Die meisten Datenbanksysteme weisen diese '' | ||
+ | |||
+ | **Interpretation** | ||
+ | |||
+ | Dass das gelieferte Ergebnis tatsächlich fragwürdig ist, zeigt sich gleich beim ersten Datensatz. Für die Region Afrika wird als Name Algerien angegeben. Hier wird also zur Gruppe Afrika das Einzeldatum Name ausgegeben. | ||
+ | |||
+ | Wir halten also fest, dass bei einer '' | ||
+ | |||
+ | </ | ||
+ | < | ||
+ | |||
+ | Wenn man nicht an allen Gruppen interessiert ist, so kann man mit der '' | ||
+ | |||
+ | Aber nach welchen Kriterien kann man Gruppen auswählen? Das geht nur mit einer Gruppeneigenschaft, | ||
+ | |||
+ | Es sollen die Regionen angezeigt werden, die mehr als 100 Millionen Einwohner haben. | ||
+ | |||
+ | < | ||
+ | <bbox w2> | ||
+ | <code sql> | ||
+ | SELECT Region, SUM(Einwohner) | ||
+ | FROM cia | ||
+ | GROUP BY Region | ||
+ | HAVING SUM(Einwohner) > 1E08 | ||
+ | </ | ||
+ | </ | ||
+ | <bbox w2> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | < | ||
+ | |||
+ | Auch eine '' | ||
+ | |||
+ | Es sollen die Einwohnerzahlen der Regionen angezeigt werden, wobei nur Länder mit mehr als 100 Millionen Einwohner berücksichtigt werden sollen. | ||
+ | |||
+ | < | ||
+ | <bbox w2> | ||
+ | <code sql> | ||
+ | SELECT Region, SUM(Einwohner) | ||
+ | FROM cia | ||
+ | WHERE Einwohner > 1E08 | ||
+ | GROUP BY Region | ||
+ | </ | ||
+ | </ | ||
+ | <bbox w2> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Um das Zustandskommen der Werte besser verstehen zu können, wandeln wir die '' | ||
+ | |||
+ | < | ||
+ | <bbox w2> | ||
+ | <code sql> | ||
+ | SELECT Region, Name, SUM(Einwohner) | ||
+ | FROM cia | ||
+ | WHERE Einwohner > 1E08 | ||
+ | GROUP BY Region, Name | ||
+ | </ | ||
+ | </ | ||
+ | <bbox w2> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | In der Region Nordamerika gibt es die zwei Länder Mexiko und die Vereinigte Staaten von Amerika mit mehr als 100 Millionen Einwohner. Die Summe ihrer Einwohnerzahlen wurde in der vorherigen Abfrage ermittelt. | ||
+ | |||
+ | </ | ||
+ | < | ||
+ | |||
+ | Kommen in einer Abfrage '' | ||
+ | |||
+ | - Zuerst werden die zu betrachtenden Datensätze mittels '' | ||
+ | - Dann werden diese mit '' | ||
+ | - Zum Schluss werden sie mit '' | ||
+ | |||
+ | Wir gruppieren wieder die Länder mit mehr als 100 Millionen Einwohner, nehmen davon aber nur die Regionen mit mehr als 250 Millionen Einwohnern. | ||
+ | |||
+ | < | ||
+ | <bbox w2> | ||
+ | <code sql> | ||
+ | SELECT Region, SUM(Einwohner) | ||
+ | FROM cia | ||
+ | WHERE Einwohner > 1E08 | ||
+ | GROUP BY Region | ||
+ | HAVING sum(Einwohner) > 250000000 | ||
+ | </ | ||
+ | </ | ||
+ | <bbox w2> | ||
+ | {{ : | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | <aufgabe w1|**Aufgabe 2**> | ||
+ | |||
+ | Nutze die [[https:// | ||
+ | |||
+ | * Zeige von jeder Region den Namen und die Anzahl der Länder an. | ||
+ | * Zeige für alle Regionen den Namen und die Anzahl der Länder mit mehr als 10 Millionen Einwohnern an. | ||
+ | * Welche Regionen haben eine Gesamtbevölkerung von mindestens 100 Millionen? | ||
+ | * Stelle die Regionen der Erde mit Einwohnerzahl und Gesamtfläche dar, geordnet nach der Einwohnerzahl. | ||
+ | * Wie Aufgabe 4 aber nur die Regionen von Amerika. | ||
+ | |||
+ | Jetzt geht es mit der [[https:// | ||
+ | |||
+ | * Ermittle die von jedem Weltmeister erreichte Gesamtzahl von WM-Punkten und stelle das Ergebnis nach WM-Punkten geordnet dar. | ||
+ | * Welche Gesamtpunktzahlen der Konstrukteursweltmeisterschaft haben die Teams in den neunziger Jahren erreicht? | ||
+ | * Wie vorherige Aufgabe, allerdings sollen nur Teams mit mindestens 100 Punkten ausgegeben werden. | ||
+ | * Ermittle für die Jahre, in denen Michael Schumacher gefahren ist, die durchschnittliche Zahl der erreichten Team-Punkte des Konstrukteursweltmeisters und stelle die Liste geordnet dar. | ||
+ | * Ermittle ab 1995 in geordneter Reihenfolge die Gesamtzahl der Team-Punkte für Teams mit mindestens 200 Punkten. | ||
+ | |||
+ | </ | ||
+ | <lösung w1 collapsed center|Lösungen zu Aufgabe 2> | ||
+ | <tabbox 1a)> | ||
+ | <code sql> | ||
+ | FROM cia | ||
+ | GROUP BY region</ | ||
+ | <tabbox 1b)> | ||
+ | <code sql> | ||
+ | FROM cia | ||
+ | WHERE Einwohner > 10E6 | ||
+ | GROUP BY region</ | ||
+ | <tabbox 1c)> | ||
+ | <code sql> | ||
+ | FROM cia | ||
+ | GROUP BY region | ||
+ | HAVING SUM(einwohner) > 100E6</ | ||
+ | <tabbox 1d)> | ||
+ | <code sql> | ||
+ | FROM cia | ||
+ | GROUP BY region | ||
+ | ORDER BY SUM(einwohner) DESC</ | ||
+ | <tabbox 1e)> | ||
+ | <code sql> | ||
+ | FROM cia | ||
+ | WHERE region LIKE ' | ||
+ | GROUP BY region | ||
+ | ORDER BY SUM(einwohner) DESC | ||
+ | </ | ||
+ | <tabbox 2a)> | ||
+ | <code sql> | ||
+ | FROM wmtitel | ||
+ | GROUP BY fahrerweltmeister | ||
+ | ORDER BY SUM(wm_punkte) DESC</ | ||
+ | <tabbox 2b)> | ||
+ | <code sql> | ||
+ | FROM wmtitel | ||
+ | WHERE saison BETWEEN 1990 AND 1999 | ||
+ | GROUP BY konstrukteurswm</ | ||
+ | <tabbox 2c)> | ||
+ | <code sql> | ||
+ | FROM wmtitel | ||
+ | WHERE saison BETWEEN 1990 AND 1999 | ||
+ | GROUP BY konstrukteurswm | ||
+ | HAVING SUM(team_punkte) > 100</ | ||
+ | <tabbox 2d)> | ||
+ | <code sql> | ||
+ | FROM WMTitel | ||
+ | WHERE Fahrerweltmeister = " | ||
+ | GROUP BY KonstrukteursWM | ||
+ | ORDER BY AVG(Team_Punkte) DESC </ | ||
+ | <tabbox 2e)> | ||
+ | <code sql> | ||
+ | FROM WMTitel | ||
+ | WHERE Saison >= 1995 | ||
+ | GROUP BY KonstrukteursWM | ||
+ | HAVING SUM(Team_Punkte) >= 200 | ||
+ | ORDER BY SUM(Team_Punkte) DESC</ | ||
+ | </ | ||
+ | </ | ||
+ | <info w1|**Zusammenfassung DQL-Statements**> | ||
+ | |||
+ | Die DQL-Anweisungen haben alle folgende grammatische Struktur, wobei optionale Anteile in [Klammern] gesetzt sind und der senkrechte Strich Alternativen beschreibt: | ||
+ | |||
+ | <code sql> | ||
+ | SELECT [DISTINCT] Selectausdruck, | ||
+ | FROM Tabellen, ... | ||
+ | [WHERE Bedingung [AND | OR] ...] | ||
+ | [GROUP BY spalten_name [ASC | DESC], ...] | ||
+ | [HAVING Bedingung [AND | OR] ...] | ||
+ | [ORDER BY spalten_name [ASC | DESC], ...] | ||
+ | [LIMIT [offset,] zeilen] | ||
+ | </ | ||
+ | |||
+ | Datenbanksysteme werteen diese Klauseln in der Reihenfolge '' | ||
+ | |||
+ | '' | ||
+ | |||
+ | </ | ||
+ | </ | ||