====== LU10: Aggregatfunktionen ====== **Datensatz**: Anzahl Einbrüche nach Gemeinden und Stadtkreisen des Kantons Zürich Um die Code-Beispiele nachvollziehen zu können, brauchen Sie die Datenbank ''zh_einbrueche'', die Sie hier als .zip-File downloaden können: {{ :modul:m290_guko:learningunits:lu10:theorie:zh_einbrueche-2025_10_31_17_01_23-dump.zip | Zip-File mit Datenbank (sql-File) zu Einbrüchen im Kanton Zürich.}} ((Datenquelle: Kantonspolizei des Kantons Zürich)) ===== 1. Aggregatfunktionen – Theorie & Motivation ===== === Was sind Aggregatfunktionen? === Aggregatfunktionen berechnen **einen zusammengefassten Wert** über mehrere Zeilen (Records). Typische Aufgaben: * **Zählen** (Wie viele Einbrüche?) * **Summieren** (Wie viele Fälle insgesamt?) * **Durchschnitt** (Ø‑Häufigkeitszahl pro Jahr) * **Minimum/Maximum** (geringste/höchste Zahl pro Gemeinde) === Wozu braucht man das? === * **Datenanalyse & Reporting** – Beispiel (Einbrüche ZH): Wie viele Fälle gab es pro Jahr? * **Nutzen:** Klare Jahreskurven für **Berichte**, **Dashboards** und **Kurzstatements** (z. B. für Polizei/Medien). * **Business Intelligence (BI)** – Beispiel (Einbrüche ZH): Welche Gemeinden haben im Schnitt höhere Raten? * **Nutzen:** **Prioritäten** setzen (Präventionskampagnen, Ressourceneinsatz, Fokus-Orte). * **Produkt-/Web-Integration** – //APIs liefern Rohdaten, Apps brauchen Kennzahlen// Beispiel (YouTube Top 100): Gesamt-Views je Channel → SUM(view_count) pro Channel; durchschnittliche Videolänge → AVG(duration) pro Channel. * **Nutzen:** Das **Backend** liefert fertige Kennzahlen; die **Frontend-Logik** bleibt schlank und schnell. ==== 1.1 Wichtigste Aggregatfunktionen ==== ^ Funktion ^ Zweck ^ NULLs ^ | ''COUNT(*)'' | Zeilen zählen | zählt **alle** Zeilen | | ''COUNT(spalte)'' | Nicht‑NULL‑Werte zählen | **ignoriert** NULL | | ''SUM(spalte)'' | Summe | ignoriert NULL | | ''AVG(spalte)'' | Durchschnitt | ignoriert NULL | | ''MIN(spalte)'' | Minimum | ignoriert NULL | | ''MAX(spalte)'' | Maximum | ignoriert NULL | **Syntax** SELECT AGGREGATFUNKTION(ausdruck) AS alias FROM zh_einbrueche.einbrueche; ==== 1.2 Einstiegsbeispiele ==== === Anzahl unterschiedlicher Gemeinden im Datensatz === SELECT COUNT(DISTINCT gemeindename) AS anzahl_gemeinden FROM zh_einbrueche.einbrueche; **Ergebnis (Auszug)** ^ anzahl_gemeinden ^ | 161 | === Höchster Einzelwert pro Zeile (Totalfälle) === SELECT MAX(straftaten_total) AS max_faelle_in_einer_zeile FROM zh_einbrueche.einbrueche; **Ergebnis (Auszug)** ^ max_faelle_in_einer_zeile ^ | 1060 | ===== 2. GROUP BY – Daten zu Gruppen zusammenfassen ===== {{ :modul:m290_guko:learningunits:lu10:theorie:group_by-sum.webp?900 |}} **Warum ist GROUP BY wichtig?** Ohne GROUP BY erhalten Sie **einen** Aggregatwert über **alle** Zeilen. Mit GROUP BY erhalten Sie **je Gruppe eine Zeile** (z.B. pro Jahr, pro Gemeinde oder pro Kombination aus Jahr+Gemeinde). Man kann so nach einzelnen Einträgen gruppieren. === Was darf in SELECT stehen? === Nur Aggregatfunktionen (z.B. SUM(...), AVG(...)) oder Spalten, die im GROUP BY aufgeführt sind. Gültig: SELECT ausgangsjahr, SUM(straftaten_total) FROM zh_einbrueche.einbrueche GROUP BY ausgangsjahr; Ungültig (fehlendes GROUP BY für gemeindename): SELECT gemeindename, SUM(straftaten_total) FROM zh_einbrueche.einbrueche; -- führt zu Fehler/Zufallswerten === WHERE vs. HAVING === * **WHERE** filtert einzelne Zeilen vor dem Gruppieren. * **HAVING** filtert fertige Gruppen nach dem Gruppieren. Beispiel: Nur Jahre ab 2018 berücksichtigen (WHERE), und nur Gruppen mit Total > 1'000 zeigen (HAVING) SELECT ausgangsjahr, SUM(straftaten_total) AS total_faelle FROM zh_einbrueche.einbrueche WHERE ausgangsjahr >= 2018 -- Zeilenfilter GROUP BY ausgangsjahr HAVING SUM(straftaten_total) > 15000; -- Gruppenfilter //Ergebnis: In den Jahren 2018, 2019 und 2024 haben über 15000 Einbrüche total stattgefunden.// ==== 2.1 Beispiele: Gruppieren nach einem Kriterium ==== **Total Einbrüche pro Jahr** SELECT ausgangsjahr, SUM(straftaten_total) AS total_faelle FROM zh_einbrueche.einbrueche GROUP BY ausgangsjahr ORDER BY ausgangsjahr; **Ergebnis (Auszug)** ^ ausgangsjahr ^ total_faelle ^ | 2009 | 29972 | | 2010 | 26770 | | 2011 | 24394 | ... etc. ==== 2.2 Beispiele: Gruppieren nach mehreren Kriterien ==== **Total pro Jahr und Tatbestand (z.B. Einbruch, Einschleichen)** SELECT ausgangsjahr, tatbestand, SUM(straftaten_total) AS total_faelle FROM zh_einbrueche.einbrueche GROUP BY ausgangsjahr, tatbestand ORDER BY ausgangsjahr, tatbestand; **Ergebnis (Auszug)** ^ ausgangsjahr ^ tatbestand ^ total_faelle ^ | 2023 | Einschleichdiebstahl | 1961 | | 2024 | Einbruchdiebstahl | 5956 | | 2024 | Einbrüche insgesamt | 7998 | ... etc. ===== 3. HAVING – Gruppen filtern ===== WHERE kann **keine** Aggregatfunktionen enthalten. Wenn Sie **Ergebnisgruppen** (nach GROUP BY) filtern wollen, verwenden Sie **HAVING**. **Jahre mit über 25'000 Fällen insgesamt** SELECT ausgangsjahr, SUM(straftaten_total) AS total_faelle FROM zh_einbrueche.einbrueche GROUP BY ausgangsjahr HAVING SUM(straftaten_total) > 25000 ORDER BY total_faelle DESC; **Ergebnis (Auszug)** ^ ausgangsjahr ^ total_faelle ^ | 2009 | 29972 | | 2012 | 28730 | | 2010 | 26770 |