NULL-Werte in Aggregatfunktionen richtig behandeln
AI generated
SELECT
JOIN
SQL · NULL-Handling · Aggregation · Datenqualität
NULL-Werte in Aggregatfunktionen
COUNT, SUM und AVG richtig einsetzen

NULL-Werte in Aggregatfunktionen werden von COUNT, SUM und AVG unterschiedlich behandelt, und genau diese Unterschiede führen regelmäßig zu falschen Durchschnittswerten und missverständlichen Reports. Dieser Artikel erklärt, warum COUNT(*) und COUNT(spalte) verschiedene Ergebnisse liefern, wie AVG durch NULL verzerrt werden kann, und wie COALESCE, NULLIF und bewusstes GROUP BY das NULL-Verhalten gezielt steuern.

13 Min. Lesezeit COUNT · SUM · AVG · COALESCE · NULLIF ANSI SQL · PostgreSQL · MySQL · SQL Server

1. Warum NULL-Werte in Aggregatfunktionen ein eigenes Thema sind

NULL-Werte in Aggregatfunktionen folgen eigenen, teils kontraintuitiven Regeln, die sich grundlegend von der Behandlung von NULL in normalen Vergleichen unterscheiden. Während ein Vergleich wie spalte = NULL in SQL grundsätzlich unbekannt statt wahr oder falsch ergibt, behandeln Aggregatfunktionen NULL nicht als dritten Wahrheitswert, sondern schlicht als Abwesenheit eines Werts, den sie bei der Berechnung ignorieren. Dieser Unterschied ist der Ausgangspunkt für die meisten Missverständnisse rund um NULL-Werte in Aggregatfunktionen.

In der Praxis führt dieses Verhalten zu Ergebnissen, die auf den ersten Blick überraschend wirken, obwohl sie exakt der SQL-Spezifikation entsprechen. Eine Spalte mit fehlenden Bewertungen, unvollständig gepflegten Preisen oder optionalen Messwerten kann eine Durchschnittsberechnung erheblich verzerren, sobald NULL nicht bewusst als eigener Fall behandelt wird. Wer die Regeln für NULL-Werte in Aggregatfunktionen einmal verinnerlicht hat, vermeidet einen der häufigsten und zugleich am schwersten zu findenden Fehlerklassen im Reporting.

Dieser Artikel geht systematisch durch das Verhalten von COUNT, SUM, AVG, MIN, MAX und booleschen Aggregatfunktionen bei NULL-Werten, zeigt typische Fallstricke bei Division und GROUP BY und stellt COALESCE sowie NULLIF als zentrale Werkzeuge vor, um NULL-Verhalten in Aggregatfunktionen gezielt zu steuern statt es dem Zufall zu überlassen.

2. COUNT(*) vs. COUNT(spalte): der Unterschied bei NULL

Der wohl häufigste Stolperstein bei NULL-Werten in Aggregatfunktionen ist der Unterschied zwischen COUNT(*) und COUNT(spalte). COUNT(*) zählt jede Zeile der Gruppe, unabhängig davon, ob einzelne Spalten NULL enthalten oder nicht. COUNT(spalte) dagegen zählt ausschließlich Zeilen, in denen genau diese Spalte einen Wert ungleich NULL enthält, und ignoriert NULL-Zeilen bei der Zählung vollständig.

Diese Unterscheidung ist besonders wichtig, wenn eine Tabelle optionale Spalten enthält, etwa eine Bewertungsspalte, die nur bei tatsächlich abgegebenen Bewertungen befüllt ist. COUNT(*) liefert dann die Gesamtzahl aller Bestellungen, während COUNT(rating) nur die Anzahl der tatsächlich bewerteten Bestellungen liefert. Wer beide Zahlen benötigt, etwa um eine Bewertungsquote zu berechnen, muss beide Varianten bewusst nebeneinander verwenden, statt versehentlich nur eine davon einzusetzen.


-- COUNT(*) vs. COUNT(column): NULL values in aggregate functions
SELECT
    product_id,
    COUNT(*) AS total_orders,          -- counts every row, NULL or not
    COUNT(rating) AS rated_orders,     -- ignores rows where rating IS NULL
    ROUND(100.0 * COUNT(rating) / COUNT(*), 1) AS rating_rate_pct
FROM order_reviews
GROUP BY product_id;

-- Result (excerpt)
-- product_id | total_orders | rated_orders | rating_rate_pct
--          1 |          200 |          140 |            70.0

3. SUM und AVG ignorieren NULL: Folgen für Durchschnitte

SUM und AVG behandeln NULL-Werte in Aggregatfunktionen identisch zueinander: Beide ignorieren NULL vollständig, statt es als null oder als fehlerhaften Wert zu interpretieren. SUM addiert nur die tatsächlich vorhandenen Werte und liefert bei einer Gruppe ausschließlich aus NULL-Werten selbst NULL zurück, nicht etwa null als Zahl. AVG teilt die Summe der vorhandenen Werte durch die Anzahl der vorhandenen, nicht durch die Gesamtanzahl der Zeilen in der Gruppe, was der eigentliche Grund für viele überraschende Durchschnittswerte ist.

Genau diese Eigenschaft von AVG wird häufig übersehen: Eine Gruppe mit fünf Zeilen, von denen nur drei einen Wert ungleich NULL enthalten, liefert bei AVG den Durchschnitt dieser drei Werte, nicht den Durchschnitt über alle fünf Zeilen mit den fehlenden Werten als null gerechnet. Wer stattdessen einen Durchschnitt über alle Zeilen inklusive der fehlenden als null erwartet, muss NULL explizit mit COALESCE in null umwandeln, bevor AVG darauf angewendet wird, sonst weicht das Ergebnis von der fachlichen Erwartung deutlich ab.


-- AVG ignores NULL rows entirely, which changes the denominator
SELECT
    product_id,
    AVG(discount_pct) AS avg_discount_ignoring_null,        -- divides by non-NULL rows only
    AVG(COALESCE(discount_pct, 0)) AS avg_discount_with_zero -- divides by ALL rows
FROM order_items
GROUP BY product_id;

-- The two results can differ substantially when many rows have no discount at all

4. COALESCE und NULLIF gezielt gegen unerwünschtes NULL einsetzen

COALESCE ist das zentrale Werkzeug, um unerwünschtes NULL-Verhalten in Aggregatfunktionen gezielt zu steuern. Die Funktion gibt den ersten Wert einer Liste zurück, der nicht NULL ist, und wird typischerweise genutzt, um einen expliziten Ersatzwert wie null anzugeben, bevor eine Spalte in eine Aggregatfunktion eingeht. Damit lässt sich das Verhalten von AVG bewusst von der Standard-Semantik, die NULL ignoriert, auf eine Semantik umstellen, die fehlende Werte als null in die Berechnung einbezieht.

NULLIF ist das logische Gegenstück zu COALESCE: Statt NULL durch einen Wert zu ersetzen, wandelt NULLIF einen bestimmten Wert bewusst in NULL um, wenn zwei Ausdrücke gleich sind. Das ist besonders bei der Vorbereitung von Aggregationen nützlich, etwa wenn ein Platzhalterwert wie minus eins in den Rohdaten eigentlich eine fehlende Messung bedeutet und vor der Aggregation als NULL behandelt werden soll, damit AVG und SUM diese Platzhalter korrekt ignorieren, statt sie fälschlich als echten Messwert einzurechnen.


-- COALESCE: turn NULL into an explicit value before aggregation
SELECT customer_id, SUM(COALESCE(bonus_points, 0)) AS total_bonus_points
FROM loyalty_transactions
GROUP BY customer_id;

-- NULLIF: turn a sentinel value into NULL so aggregate functions ignore it
SELECT sensor_id, AVG(NULLIF(reading, -1)) AS avg_reading_excluding_sentinel
FROM sensor_readings
GROUP BY sensor_id;

5. Division durch null und NULLIF als Schutz vor Fehlern

Ein besonders praktischer Anwendungsfall für NULLIF im Kontext von NULL-Werten in Aggregatfunktionen ist der Schutz vor einer Division durch null, die in fast allen Datenbanksystemen einen Fehler auslöst und die gesamte Abfrage abbrechen lässt. Berichte, die Quoten oder Prozentsätze berechnen, etwa Konversionsraten aus COUNT-Ergebnissen, sind besonders anfällig, sobald der Nenner für eine bestimmte Gruppe zufällig null ergibt.

NULLIF(nenner, 0) wandelt einen Nenner von null in NULL um, und eine Division durch NULL liefert in SQL zuverlässig NULL statt eines Fehlers. Das Ergebnis der betroffenen Zeile wird dann NULL statt eines Laufzeitfehlers, was sich in den meisten Reporting-Werkzeugen als leerer oder als nicht verfügbarer Wert darstellen lässt, statt den gesamten Bericht abstürzen zu lassen. Diese Technik gehört in jede Abfrage, die eine Division auf Basis von aggregierten Zählwerten durchführt.


-- Protect against division by zero using NULLIF
SELECT
    campaign_id,
    COUNT(*) FILTER (WHERE converted) AS conversions,
    COUNT(*) AS total_visits,
    ROUND(
        100.0 * COUNT(*) FILTER (WHERE converted) / NULLIF(COUNT(*), 0),
        2
    ) AS conversion_rate_pct
FROM campaign_visits
GROUP BY campaign_id;

6. GROUP BY und NULL: eigene Gruppe statt Ausschluss

Ein weiterer wichtiger Aspekt von NULL-Werten in Aggregatfunktionen betrifft das Zusammenspiel mit GROUP BY. Anders als man vielleicht erwarten würde, schließt GROUP BY Zeilen mit NULL in der Gruppierungsspalte nicht aus, sondern bildet für alle NULL-Zeilen eine eigene, gemeinsame Gruppe. Alle Zeilen, deren Gruppierungsspalte NULL ist, landen also zusammen in genau einer Ergebniszeile, unabhängig davon, wie viele unterschiedliche fachliche Gründe für das jeweilige NULL vorliegen.

Das kann zu einer unerwarteten Zusammenfassung führen, wenn NULL in der Gruppierungsspalte aus verschiedenen Ursachen entsteht, etwa "Kategorie noch nicht zugewiesen" und "Kategorie absichtlich leer" gleichzeitig. Aggregatfunktionen wie SUM oder COUNT innerhalb dieser NULL-Gruppe fassen dann fachlich unterschiedliche Fälle in einer einzigen Zeile zusammen. Wer diese Vermischung vermeiden möchte, sollte NULL in der Gruppierungsspalte vor der Aggregation mit COALESCE in einen aussagekräftigen Platzhaltertext wie "Nicht zugewiesen" umwandeln, damit die Gruppe im Ergebnis eindeutig erkennbar bleibt.

7. Boolesche Aggregation mit NULL: BOOL_OR und COUNT(CASE WHEN...)

PostgreSQL bietet mit BOOL_OR und BOOL_AND eigene Aggregatfunktionen für boolesche Spalten, die ebenfalls NULL-Werte in Aggregatfunktionen ignorieren, wie es für Aggregatfunktionen üblich ist. BOOL_OR liefert wahr, sobald mindestens eine nicht-NULL-Zeile der Gruppe wahr ist, BOOL_AND liefert nur dann wahr, wenn alle nicht-NULL-Zeilen wahr sind. In Datenbanksystemen ohne native boolesche Aggregatfunktionen, etwa MySQL oder SQL Server, übernimmt COUNT(CASE WHEN bedingung THEN 1 END) dieselbe Aufgabe, ergänzt um einen Vergleich mit null oder der Gesamtanzahl.

Der Vorteil von COUNT(CASE WHEN...) gegenüber einer direkten SUM(bedingung)-Konstruktion liegt darin, dass CASE WHEN explizit steuert, was bei NULL in der geprüften Spalte passieren soll, statt sich auf implizites Verhalten der Vergleichsoperatoren zu verlassen. Diese Konstruktion ist auch die Grundlage der bedingten Aggregation, mit der sich mehrere Kennzahlen unterschiedlicher Bedingungen in einer einzigen Abfrage nebeneinander berechnen lassen, ohne mehrere separate Abfragen zu benötigen.


-- Boolean aggregation with NULL-aware conditional counting
SELECT
    order_id,
    BOOL_OR(is_returned) AS any_item_returned,         -- PostgreSQL native
    COUNT(CASE WHEN is_returned THEN 1 END) AS returned_item_count,
    COUNT(*) AS total_item_count
FROM order_items
GROUP BY order_id;

8. HAVING und NULL-Vergleiche: typische Fallstricke

HAVING filtert Ergebnisse nach der Aggregation, und auch hier spielen NULL-Werte in Aggregatfunktionen eine Rolle, die leicht übersehen wird. Ein Ausdruck wie HAVING SUM(betrag) = NULL liefert niemals ein Ergebnis, weil ein Vergleich mit NULL in SQL grundsätzlich unbekannt statt wahr ergibt, selbst wenn SUM tatsächlich NULL zurückgegeben hat. Der korrekte Ausdruck lautet HAVING SUM(betrag) IS NULL, mit dem expliziten IS-NULL-Operator statt eines Gleichheitsvergleichs.

Dieser Fallstrick betrifft insbesondere Reports, die Gruppen ohne jegliche gültige Werte herausfiltern möchten, etwa Produkte ohne einzige Bewertung. Wer versehentlich = NULL statt IS NULL schreibt, erhält keine Fehlermeldung, sondern schlicht ein leeres oder unvollständiges Ergebnis, ohne dass der Grund dafür sofort ersichtlich wäre. Dieser Unterschied zwischen Gleichheitsvergleich und IS-NULL-Prüfung gehört zu den grundlegendsten, aber am häufigsten übersehenen Regeln im Umgang mit NULL in SQL überhaupt.

9. NULL-Verhalten der Aggregatfunktionen im Vergleich

Die folgende Übersicht fasst zusammen, wie die wichtigsten Aggregatfunktionen mit NULL-Werten umgehen, damit beim Schreiben eines Reports von Anfang an das richtige Verhalten erwartet wird.

Funktion Verhalten bei NULL Ergebnis bei ausschließlich NULL
COUNT(*) Zählt jede Zeile, NULL spielt keine Rolle Anzahl aller Zeilen
COUNT(spalte) Ignoriert Zeilen mit NULL in der Spalte 0
SUM Ignoriert NULL bei der Addition NULL, nicht 0
AVG Teilt durch Anzahl der Nicht-NULL-Werte NULL
MIN / MAX Ignoriert NULL bei der Vergleichssuche NULL

Mironsoft

Datenqualität, SQL-Reporting und Query-Review

Durchschnittswerte, die sich einfach falsch anfühlen?

Wir prüfen bestehende Reports gezielt auf unbeabsichtigtes NULL-Verhalten in Aggregatfunktionen und sorgen mit COALESCE, NULLIF und sauberem GROUP BY für Kennzahlen, die fachlich tatsächlich stimmen.

NULL-Audit

Prüfung bestehender Reports auf unerwartetes COUNT-, SUM- und AVG-Verhalten

Query-Refactoring

Gezielter Einsatz von COALESCE und NULLIF in bestehenden Aggregationen

Datenqualität

Analyse, warum bestimmte Spalten überhaupt NULL enthalten, statt nur Symptome zu kurieren

Wer NULL-Werte in Aggregatfunktionen von Anfang an bewusst behandelt statt sich auf implizites Verhalten zu verlassen, vermeidet nicht nur falsche Durchschnittswerte, sondern auch schwer nachvollziehbare Diskussionen darüber, warum ein Report bei genauerem Hinsehen doch nicht ganz stimmt.

10. Zusammenfassung

NULL-Werte in Aggregatfunktionen folgen einer konsistenten, aber leicht zu übersehenden Regel: Aggregatfunktionen ignorieren NULL bei der Berechnung, statt es als null oder Fehlwert zu behandeln. COUNT(*) und COUNT(spalte) liefern deshalb unterschiedliche Ergebnisse, AVG teilt nur durch die Anzahl der vorhandenen Werte, und SUM über ausschließlich NULL-Werte liefert selbst NULL zurück. COALESCE ersetzt NULL gezielt durch einen expliziten Wert, NULLIF wandelt umgekehrt einen bestimmten Wert bewusst in NULL um.

Wer diese Regeln kennt, vermeidet die häufigsten Fehlerquellen im Reporting: verzerrte Durchschnitte, Divisionen durch null und stillschweigend übersehene HAVING-Bedingungen mit falschem Gleichheitsvergleich statt IS NULL. Auch GROUP BY verdient besondere Aufmerksamkeit, weil NULL-Zeilen dort zu einer eigenen, potenziell fachlich vermischten Gruppe zusammengefasst werden, statt einfach ausgeschlossen zu werden.

NULL-Werte in Aggregatfunktionen: das Wichtigste auf einen Blick

COUNT-Unterschied

COUNT(*) zählt alle Zeilen, COUNT(spalte) ignoriert Zeilen mit NULL in genau dieser Spalte.

AVG-Nenner

AVG teilt durch die Anzahl der Nicht-NULL-Werte, nicht durch die Gesamtanzahl der Zeilen.

COALESCE und NULLIF

COALESCE ersetzt NULL durch einen Wert, NULLIF wandelt einen Wert gezielt in NULL um.

HAVING mit NULL

Immer IS NULL statt = NULL verwenden, sonst liefert die Bedingung nie ein Ergebnis.

11. FAQ: NULL-Werte in Aggregatfunktionen

1Wie behandeln Aggregatfunktionen NULL?
Sie ignorieren NULL vollständig bei der Berechnung, statt es als null oder Fehler zu behandeln.
2COUNT(*) vs. COUNT(spalte)?
COUNT(*) zählt alle Zeilen, COUNT(spalte) ignoriert Zeilen mit NULL in dieser Spalte.
3Warum überrascht AVG manchmal?
AVG teilt nur durch die Anzahl der Nicht-NULL-Werte, nicht durch alle Zeilen der Gruppe.
4NULL gezielt in einen Wert umwandeln?
Mit COALESCE(spalte, ersatzwert) vor der Aggregation.
5Wozu dient NULLIF hier?
Wandelt einen bestimmten Wert wie einen Platzhalter bewusst in NULL um, damit er ignoriert wird.
6Division durch null vermeiden?
NULLIF(nenner, 0) wandelt null in NULL um, die Division liefert dann NULL statt eines Fehlers.
7NULL bei GROUP BY?
Alle NULL-Zeilen landen in einer gemeinsamen Gruppe, statt ausgeschlossen zu werden.
8Warum liefert = NULL nie ein Ergebnis?
Vergleiche mit NULL ergeben immer unbekannt, statt wahr. IS NULL ist der korrekte Operator.
9Boolesche Aggregation mit NULL?
BOOL_OR/BOOL_AND in PostgreSQL, sonst COUNT(CASE WHEN bedingung THEN 1 END).
10SUM über nur NULL-Werte ergibt 0?
Nein, SUM liefert NULL. COALESCE(SUM(spalte), 0) erzwingt bei Bedarf den Wert 0.