SQL COUNT, SUM, AVG

6 Kernkonzepte
Die wichtigsten SQL-Aggregatfunktionen für Berechnungen: COUNT · SUM · AVG · MIN · MAX · GROUP BY Aggregatfunktionen fassen viele Zeilen zu einem einzigen Wert zusammen. Sie sind unverzichtbar für Analysen, Berichte und Statistiken in Datenbanken.

COUNT – Zeilen zählen

COUNT(*) · COUNT(spalte) · COUNT(DISTINCT spalte)
SELECT COUNT(*) FROM kunden; SELECT COUNT(email) FROM kunden; SELECT COUNT(DISTINCT kategorie) FROM produkte;

COUNT zählt die Anzahl der Zeilen. COUNT(*) zählt alle Zeilen inkl. NULL, COUNT(spalte) zählt nur nicht-NULL-Werte, COUNT(DISTINCT spalte) zählt eindeutige Werte.

COUNT-Varianten

Variante Beschreibung Beispiel
COUNT(*) Alle Zeilen (inkl. NULL) SELECT COUNT(*) FROM kunden
COUNT(spalte) Nur Zeilen mit nicht-NULL-Wert SELECT COUNT(email) FROM kunden
COUNT(DISTINCT spalte) Eindeutige Werte SELECT COUNT(DISTINCT kategorie) FROM produkte
COUNT(1) Wie COUNT(*) (Performance-Konvention) SELECT COUNT(1) FROM kunden
Beispiele
-- Alle Kunden zählen
SELECT COUNT(*) AS "anzahl" FROM kunden;
-- Kunden mit E-Mail zählen (NULL ausgeschlossen)
SELECT COUNT(email) FROM kunden;
-- Verschiedene Kategorien
SELECT COUNT(DISTINCT kategorie) FROM produkte;
-- COUNT mit WHERE
SELECT COUNT(*) FROM bestellungen
WHERE datum >= '2024-01-01';
Typische Ausgabe:
anzahl
42
Tipp: COUNT(*) zählt alle Zeilen, COUNT(spalte) nur nicht-NULL-Werte. Wenn Sie die tatsächliche Anzahl der Datensätze benötigen (inkl. NULL), verwenden Sie COUNT(*).

SUM – Werte summieren

SUM(spalte) · SUM(DISTINCT spalte)
SELECT SUM(preis) FROM produkte; SELECT SUM(menge * preis) FROM bestellpositionen;

SUM berechnet die Summe aller Werte einer Spalte. Funktioniert nur mit numerischen Datentypen. NULL-Werte werden ignoriert.

Beispiele
-- Gesamtumsatz aller Produkte
SELECT SUM(preis) AS "gesamt" FROM produkte;
-- Summe mit Berechnung (Menge * Preis)
SELECT SUM(menge * einzelpreis) AS "umsatz"
FROM bestellpositionen;
-- Nur bestimmte Produkte summieren
SELECT SUM(preis) FROM produkte
WHERE kategorie = 'Elektronik';
-- SUM(DISTINCT) – summiert eindeutige Werte (selten)
SELECT SUM(DISTINCT preis) FROM produkte;
Typische Ausgabe:
gesamt
12499.99
Tipp: SUM ignoriert NULL-Werte. Wenn alle Werte einer Spalte NULL sind, gibt SUM NULL zurück – verwenden Sie COALESCE(SUM(spalte), 0) für eine 0.

AVG – Durchschnitt berechnen

AVG(spalte) · AVG(DISTINCT spalte)
SELECT AVG(preis) FROM produkte; SELECT AVG(preis) FROM produkte WHERE kategorie = 'Elektronik';

AVG berechnet den Durchschnitt (Mittelwert) aller Werte einer Spalte. Funktioniert nur mit numerischen Datentypen. NULL-Werte werden ignoriert.

Beispiele
-- Durchschnittlicher Preis aller Produkte
SELECT AVG(preis) AS "durchschnitt" FROM produkte;
-- Durchschnitt pro Kategorie (mit GROUP BY)
SELECT kategorie, AVG(preis) AS "durchschnitt"
FROM produkte
GROUP BY kategorie;
-- Durchschnitt mit ROUND (2 Nachkommastellen)
SELECT ROUND(AVG(preis), 2) AS "durchschnitt"
FROM produkte;
-- AVG(DISTINCT) – Durchschnitt der eindeutigen Werte
SELECT AVG(DISTINCT preis) FROM produkte;
Typische Ausgabe:
durchschnitt
124.99
Tipp: AVG ignoriert NULL-Werte. Wenn Sie den Durchschnitt über alle Zeilen inkl. NULL berechnen möchten, müssen Sie NULL durch einen Wert ersetzen (z.B. mit COALESCE(spalte, 0)).

MIN & MAX – Minimum & Maximum

MIN(spalte) · MAX(spalte)
SELECT MIN(preis) AS "min", MAX(preis) AS "max" FROM produkte;

MIN und MAX geben den kleinsten bzw. größten Wert einer Spalte zurück. Sie funktionieren mit numerischen, textuellen und Datumsspalten.

Beispiele
-- Günstigstes und teuerstes Produkt
SELECT
MIN(preis) AS "min",
MAX(preis) AS "max"
FROM produkte;
-- Älteste und neueste Bestellung
SELECT MIN(datum) AS "älteste", MAX(datum) AS "neueste"
FROM bestellungen;
-- Alphabetisch erster und letzter Kunde
SELECT MIN(name) AS "erster", MAX(name) AS "letzter"
FROM kunden;
-- MIN/MAX mit GROUP BY
SELECT kategorie, MIN(preis) AS "min", MAX(preis) AS "max"
FROM produkte
GROUP BY kategorie;
Typische Ausgabe:
min | max
9.99 | 999.99
Tipp: MIN und MAX ignorieren NULL-Werte. Bei Textspalten wird die alphabetische Reihenfolge verwendet (A ist minimal, Z ist maximal).

GROUP BY – Daten gruppieren

GROUP BY spalte · HAVING
SELECT kategorie, COUNT(*) FROM produkte GROUP BY kategorie;

GROUP BY gruppiert Zeilen mit gleichen Werten und ermöglicht Aggregation pro Gruppe. HAVING filtert die Gruppen (ähnlich wie WHERE für Zeilen).

Beispiele
-- Anzahl Produkte pro Kategorie
SELECT kategorie, COUNT(*) AS "anzahl"
FROM produkte
GROUP BY kategorie;
-- Durchschnittspreis pro Kategorie
SELECT kategorie, AVG(preis) AS "durchschnitt"
FROM produkte
GROUP BY kategorie;
-- Umsatz pro Kunde (mit JOIN)
SELECT k.name, SUM(b.betrag) AS "umsatz"
FROM kunden k
JOIN bestellungen b ON k.id = b.kunde_id
GROUP BY k.id, k.name;
-- HAVING: Nur Kategorien mit mehr als 5 Produkten
SELECT kategorie, COUNT(*) AS "anzahl"
FROM produkte
GROUP BY kategorie
HAVING COUNT(*) > 5;
-- HAVING mit AVG: Kategorien mit Durchschnittspreis über 100
SELECT kategorie, AVG(preis) AS "durchschnitt"
FROM produkte
GROUP BY kategorie
HAVING AVG(preis) > 100;
Typische Ausgabe (GROUP BY kategorie):
kategorie | anzahl
Elektronik | 15
Bücher | 8
Kleidung | 5
Tipp: GROUP BY und HAVING sind mächtig, aber teuer bei großen Datenmengen. Stellen Sie sicher, dass die gruppierten Spalten indiziert sind, um die Performance zu verbessern.

Praxis-Beispiele – Aggregationen im Einsatz

Analysen · Berichte · Statistiken
-- Gesamtumsatz pro Monat SELECT DATE_TRUNC('month', datum) AS "monat", SUM(betrag) AS "umsatz" FROM bestellungen GROUP BY "monat" ORDER BY "monat";

Praxis-Beispiele zeigen die Kombination von Aggregatfunktionen mit GROUP BY für typische Analyse-Aufgaben wie Umsatzberichte, Bestandsanalysen und Auswertungen.

Beispiele
-- Anzahl Bestellungen pro Kunde
SELECT k.name, COUNT(b.id) AS "bestellungen"
FROM kunden k
LEFT JOIN bestellungen b ON k.id = b.kunde_id
GROUP BY k.id, k.name
ORDER BY "bestellungen" DESC;
-- Durchschnittlicher Bestellwert pro Kunde
SELECT k.name, AVG(b.betrag) AS "durchschnitt"
FROM kunden k
JOIN bestellungen b ON k.id = b.kunde_id
GROUP BY k.id, k.name
HAVING COUNT(b.id) > 1;
-- Jahresumsatz pro Kategorie (MySQL)
SELECT YEAR(b.datum) AS "jahr",
p.kategorie,
SUM(bp.menge * bp.einzelpreis) AS "umsatz"
FROM bestellungen b
JOIN bestellpositionen bp ON b.id = bp.bestellung_id
JOIN produkte p ON bp.produkt_id = p.id
GROUP BY "jahr", p.kategorie
ORDER BY "jahr", p.kategorie;
-- PostgreSQL: mit DATE_TRUNC
SELECT DATE_TRUNC('quarter', datum) AS "quartal",
COUNT(*) AS "anzahl",
SUM(betrag) AS "umsatz"
FROM bestellungen
GROUP BY "quartal"
ORDER BY "quartal";
Typische Ausgabe (Bestellungen pro Kunde):
name | bestellungen
Max Mustermann | 12
Anna Schmidt | 8
Ben Weber | 3
Tipp: Für komplexe Analysen mit mehreren Aggregationen und Fensterfunktionen wie ROW_NUMBER(), RANK() oder LAG() bieten sich Window Functions an – ein fortgeschrittenes Thema für weiterführende Analysen.

Aggregatfunktionen im Überblick

COUNT Zeilen zählen
* oder Spalte
SUM Werte summieren
Nur numerisch
AVG Durchschnitt
Nur numerisch
MIN Kleinsten Wert
Numerisch, Text, Datum
MAX Größten Wert
Numerisch, Text, Datum
GROUP BY Gruppierung
HAVING für Filter

Quick Summary

COUNT
Zählen
SUM
Summieren
AVG
Durchschnitt
MIN/MAX
Min/Max
GROUP BY
Gruppieren
HAVING
Gruppen filtern
SELECT kategorie, COUNT(*), AVG(preis), SUM(bestand) FROM produkte GROUP BY kategorie HAVING COUNT(*) > 5;