3.9 HAVING

Sollen in einem Abfrageergebnis, das aus gruppierten Datensätzen besteht, nur die Gruppen verbleiben, die eine oder mehrere Bedingungen erfüllen, müssen diese Bedingungen im HAVING-Abschnitt formuliert werden. Die WHERE-Klausel ist hierfür ungeeignet, da deren Bedingungen geprüft werden bevor Datensätze gruppiert werden.

Beispiel

Gewünscht wird eine Übersicht, die für alle vorhandenen Fahrradtypen (Fahrradtyp_ID) jeweils die Summe der Anschaffungskosten aller Fahrräder diesen Typs ausweist. Berücksichtig werden sollen jedoch nur die Fahrradtypen, bei denen diese Summe mindestens 1.500 EUR beträgt.

  1. Die Tabelle Fahrrad enthält sowohl die Fahrradtyp_ID als auch die Anschaffungskosten eines jeden Fahrrads.

    Tabelle Fahrrad

    ID Kennung Anschaffungskosten ↑Fahrradtyp_ID
    1 Cross#7 670.00 1
    2 Mark#2 750.00 2
    3 Silver#1 850.00 2
    4 Winter#1 730.00 1
    Abb. 3-106: Tabelle Fahrrad
  2. Mit Hilfe der GROUP BY-Klausel fassen wir im Abfrageergebnis alle Datensätze, die in der Spalte Fahrradtyp_ID den gleichen Wert besitzen, zu einer Gruppe zusammen. Die Aggregatfunktion SUM(Anschaffungskosten) addiert nun für jede Gruppe die Werte der Spalte Anschaffungskosten.

    SQL
    SELECT Fahrradtyp_ID, SUM(Anschaffungskosten) AS Anschaffungskosten
    FROM Fahrrad
    GROUP BY Fahrradtyp_ID;
    Abb. 3-107: SQL-Anweisung

    Abfrageergebnis

    Fahrradtyp_ID Anschaffungskosten
    1 1400.00
    2 1600.00
    Abb. 3-108: Abfrageergebnis der SQL-Anweisung aus Abb. 3-107.
  3. Mit Hilfe der HAVING-Klausel erreichen wir, dass im Abfrageergebnis nur die Gruppen verbleiben, deren Datensätze in der Spalte Anschaffungskosten Werte besitzen, die zusammengerechnet mindestens 1.500 EUR betragen.

    SQL
    SELECT Fahrradtyp_ID, SUM(Anschaffungskosten) AS Anschaffungskosten
    FROM Fahrrad
    GROUP BY Fahrradtyp_ID
    HAVING SUM(Anschaffungskosten) > 1500;
    Abb. 3-109: SQL-Anweisung

    Abfrageergebnis

    Fahrradtyp_ID Anschaffungskosten
    2 1600.00
    Abb. 3-110: Abfrageergebnis der SQL-Anweisung aus Abb. 3-109.

    Der SQL-Standard sieht vor, dass der HAVING-Abschnitt vor dem SELECT-Abschnitt verarbeitet wird. Der im SELECT-Abschnitt definierte Spaltenname (Alias) Kosten kann im HAVING-Abschnitt daher eigentlich nicht verwendet werden. MySQL erlaubt dies jedoch in seinen Standardeinstellungen.

Die HAVING-Klausel kann Bedingungen aufnehmen, die sich auf aggregierte Werte gruppierter Datensätze beziehen.

SQL
SELECT [DISTINCT] spalte [, ...]
FROM tabelle [INNER JOIN tabelle2 ON tabelle.fremdschlüssel = tabelle2.primärschluessel]
[WHERE bedingung]
[GROUP BY spalte [, ...]]
[HAVING bedingung]
[ORDER BY {spalte [ASC|DESC]} [, ...]];
Abb. 3-111: SQL Syntax – SELECT-Anweisung inklusive HAVING-Abschnitt
Merke: Gruppieren von Datensätzen im Abfrageergebnis
Aufgabe

Aufgabe 3-14: Bedingungen, die sich auf aggregierte Werte gruppierter Datensätze beziehen.

Datenbank Firmenwagen

Erstellen Sie jeweils eine SQL-Anweisung, die als Abfrageergebnis eine Tabelle mit den gewünschten Daten zurückgibt:

  1. Gewünscht wird eine Übersicht, die für alle Fahrzeuge (Fahrzeug_ID), die bereits mindestens einmal in der Instandhaltung waren, zeigt, wie oft diese bereits dort waren und wie hoch die dabei angefallenen durchschnittlichen Kosten sind. Die Übersicht soll nur die Fahrzeuge zeigen, bei denen die durchschnittlichen Kosten 330 EUR übersteigen. Lösung
    Lösung
    SQL
    SELECT Fahrzeug_ID, COUNT(*) AS AnzahlInstandhaltungen, AVG(Kosten) AS Durchschnittskosten
    FROM Instandhaltung
    GROUP BY Fahrzeug_ID
    HAVING AVG(Kosten) > 330;
    Abb. 3-112: SQL-Anweisung
  2. Gewünscht wird eine Übersicht, die für jedes Fahrzeugmodell (Modellbezeichnung, Hersteller) zeigt, wie viele Fahrzeuge jeweils vorhanden sind. Berücksichtigt werden sollen dabei nur Modelle, von denen mindestens zwei Fahrzeuge im Bestand sind. Lösung
    Lösung
    SQL
    SELECT Hersteller, Bezeichnung, COUNT(*) AS AnzahlFahrzeuge
    FROM Fahrzeug INNER JOIN Fahrzeugmodell ON Fahrzeugmodell_ID=Fahrzeugmodell.ID
    GROUP BY Hersteller, Bezeichnung
    HAVING COUNT(*) >= 2;
    Abb. 3-113: SQL-Anweisung
  3. Gewünscht wird eine Übersicht, die die Gesamtkosten aller Versicherungsverträge je Versicherungsgesellschaft (Firma) zeigt, sofern die Gesamtkosten 3.000 EUR übersteigen. Lösung
    Lösung
    SQL
    SELECT Firma, SUM(Beitrag) AS Kosten
    FROM Versicherungsvertrag INNER JOIN Versicherungsgesellschaft ON Versicherungsvertrag.Gesellschaft_ID=Versicherungsgesellschaft.ID
    GROUP BY Firma
    HAVING SUM(Beitrag) > 3000;
    Abb. 3-114: SQL-Anweisung