COUNT(*) vs COUNT(spalte) vs COUNT(DISTINCT spalte)
COUNT(*) zaehlt alle Tupel einer Gruppe inklusive Zeilen, die ausschliesslich NULL-Werte enthalten. COUNT(spalte) zaehlt nur diejenigen Zeilen,
bei denen die angegebene Spalte einen definierten Wert ungleich NULL hat. COUNT(DISTINCT spalte) zaehlt die Anzahl unterschiedlicher, nicht-NULL
Auspraegungen einer Spalte, was zur Duplikate-Eliminierung dient. Diese drei Varianten liefern in der Regel unterschiedliche Zahlen und werden
gerne in Multiple-Choice-Fragen verwechselt.
Stern zaehlt Zeilen, Spalte zaehlt Werte, DISTINCT zaehlt Auspraegungen - NULL zaehlt nur der Stern mit.
NULL-Behandlung in Aggregaten
Die meisten DBMS ignorieren NULL-Werte in Aggregatfunktionen wie SUM, AVG, MIN, MAX und COUNT(spalte). Ein AVG(note) rechnet nur den Durchschnitt
der nicht-NULL Noten, wodurch der Nenner kleiner sein kann als die Gesamtzahl der Tupel. Bei einer Spalte, die ausschliesslich NULL enthaelt, liefert
SUM/AVG/MIN/MAX ebenfalls NULL zurueck, nur COUNT(*) liefert die Zeilenzahl. Diese Semantik weicht bewusst von einfachen Rechenoperationen ab, weil
NULL als unbekannt statt als 0 interpretiert wird.
NULL wird in Aggregaten uebersprungen - AVG mittelt nur was da ist, nicht was fehlt.
GROUP BY - Gruppierung
GROUP BY bildet Gruppen aus Tupeln, die in einer oder mehreren Spalten gleiche Werte haben, und liefert pro Gruppe genau ein Ergebnistupel. Alle
in der SELECT-Klausel aufgefuehrten Attribute muessen entweder in der GROUP BY-Klausel stehen oder durch eine Aggregatfunktion umschlossen sein.
Ohne diese Regel waere unklar, welcher Wert einer Gruppe in einer nicht aggregierten Spalte ausgegeben werden soll. Die Gruppierung erlaubt Fragen
wie Summe pro Professor oder Anzahl pro Semester.
Was nicht gruppiert wird, muss aggregiert werden - sonst Fehler.
HAVING - Filter fuer Gruppen
HAVING enthaelt Filterbedingungen, die nach der Gruppierung auf die entstandenen Gruppen angewendet werden, aehnlich zu WHERE fuer ungruppierte
Anfragen. In HAVING duerfen Aggregatfunktionen wie AVG(sws) >= 3 verwendet werden, in WHERE dagegen nicht. Der Unterschied ist zeitlich: WHERE
filtert einzelne Zeilen vor GROUP BY, HAVING filtert ganze Gruppen nach GROUP BY. In der Ausfuehrungsreihenfolge steht HAVING an Position 4, nach
FROM/JOIN, WHERE und GROUP BY.
WHERE filtert Zeilen vor Gruppierung, HAVING filtert Gruppen danach.
Ausfuehrungsreihenfolge von SQL-Klauseln
SQL wird logisch in folgender Reihenfolge ausgefuehrt: 1. FROM/JOIN, 2. WHERE, 3. GROUP BY, 4. HAVING, 5. SELECT, 6. DISTINCT, 7. ORDER BY,
8. Mengenoperationen. Diese Reihenfolge erklaert, warum Aliase aus SELECT nicht in WHERE genutzt werden koennen, aber in ORDER BY schon. Sie ist
zentral fuer das Verstehen komplexer Abfragen mit Aggregatfunktionen. Die Ausfuehrungsreihenfolge unterscheidet sich absichtlich von der
Schreibreihenfolge, die mit SELECT beginnt.
FROM-WHERE-GROUP-HAVING-SELECT-DISTINCT-ORDER: erst filtern, dann gruppieren, dann aggregieren.
Die fuenf Standardaggregate
AVG berechnet den arithmetischen Mittelwert nicht-NULL Werte einer numerischen Spalte. SUM addiert alle nicht-NULL Werte, MIN und MAX liefern
den kleinsten bzw. groessten definierten Wert. COUNT ist die einzige Aggregatfunktion, die auch mit dem Sternoperator arbeiten kann und dann alle
Zeilen zaehlt. Alle Aggregate reduzieren eine Menge auf einen Skalarwert und koennen per AS umbenannt werden, zum Beispiel SUM(sws) AS deputat.
AVG, SUM, MIN, MAX, COUNT - fuenf Aggregate reduzieren Mengen zu einem Wert.
Skalare Unterabfrage mit Aggregat
Ein haeufiges Muster ist die skalare Unterabfrage, die genau einen Wert per Aggregat liefert und in WHERE mit einem Attribut verglichen wird.
Ein typisches Beispiel ist WHERE semester = (SELECT MAX(semester) FROM studenten), um den Studenten mit den meisten Semestern zu ermitteln.
Wichtig: Die Unterabfrage muss genau ein Tupel liefern, sonst gibt es einen Laufzeitfehler. Dies loest das klassische Problem, dass MAX allein nur
den Wert, aber nicht die zugehoerige Zeile liefert.
MAX kennt nur den Wert - fuer die Zeile braucht es eine Unterabfrage.
AS-Alias fuer Aggregatspalten
Ergebnisse von Aggregatfunktionen bekommen ohne AS-Klausel oft einen unlesbaren automatischen Spaltennamen wie SUM(sws). Mit AS deputat wird die
Spalte klar benannt und kann in ORDER BY (nicht aber in HAVING oder WHERE der gleichen Anfrage) referenziert werden. Dies dient der Lesbarkeit und
erleichtert die Weiterverwendung in Programmen. Der AS-Operator kann auch Relationen umbenennen, zum Beispiel FROM studenten AS s.
Ohne AS bleibt SUM(sws) - mit AS wird deputat draus.