Skip to article frontmatterSkip to article content

Warum sind Abfragen so wichtig?

Daten in einer Datenbank zu speichern ist nur der erste Schritt – der wahre Wert liegt darin, diese Daten wieder abzurufen und zu analysieren. Die SELECT-Anweisung ist das Herzstück von SQL und ermöglicht es dir:

Ob du eine einfache Liste von Vereinsmitgliedern abrufen oder komplexe statistische Auswertungen durchführen möchtest – die SELECT-Anweisung ist dein wichtigstes Werkzeug.

Grundstruktur einer SELECT-Anweisung

Eine vollständige SELECT-Anweisung kann sehr komplex sein, aber die Grundstruktur lässt sich in folgende Komponenten unterteilen:

SELECT [DISTINCT] spaltenliste           -- Welche Spalten sollen angezeigt werden?
FROM tabelle                             -- Aus welcher Tabelle?
[WHERE bedingung]                        -- Welche Zeilen sollen gefiltert werden?
[GROUP BY gruppierungsspalten]           -- Wie sollen die Daten gruppiert werden?
[HAVING gruppierungsbedingung]           -- Welche Gruppen sollen gefiltert werden?
[ORDER BY sortierspalten [ASC|DESC]]     -- Wie sollen die Ergebnisse sortiert werden?
[LIMIT anzahl [OFFSET startposition]];   -- Wie viele Ergebnisse sollen angezeigt werden?

Die eckigen Klammern kennzeichnen optionale Komponenten. Nur die Teile SELECT und FROM sind obligatorisch.

Einfache SELECT-Anweisungen

Die grundlegendste Form einer Abfrage wählt alle Spalten aus einer Tabelle aus:

-- Alle Spalten und alle Zeilen aus der Tabelle 'Person' auswählen
SELECT * FROM Person;

Das Sternchen * ist ein Platzhalter für “alle Spalten”. In der Praxis ist es jedoch oft besser, nur die benötigten Spalten explizit anzugeben:

-- Nur Namen und Vornamen aller Personen auswählen
SELECT Name, Vorname FROM Person;

Dies verbessert die Lesbarkeit, reduziert die Datenmenge und kann die Abfragegeschwindigkeit erhöhen.

Spaltenaliase

Du kannst Spalten in den Ergebnissen umbenennen, indem du Aliase verwendest:

-- Spalten mit benutzerfreundlicheren Namen anzeigen
SELECT 
    Name AS Nachname,
    Vorname AS Rufname
FROM Person;

In den Ergebnissen erscheinen die Spalten nun als “Nachname” und “Rufname”, was besonders nützlich ist, wenn du die Ergebnisse an eine Anwendung weitergibst oder für Berichte verwendest.

Filtern mit WHERE

Die meisten Abfragen müssen die Ergebnisse auf bestimmte Zeilen beschränken. Die WHERE-Klausel erlaubt es dir, Bedingungen zu definieren, die jede zurückgegebene Zeile erfüllen muss:

-- Alle aktiven Personen auswählen (ohne Austrittsdatum)
SELECT Name, Vorname, Eintritt 
FROM Person
WHERE Austritt IS NULL;

-- Alle Personen, die nach dem 1.1.2020 eingetreten sind
SELECT Name, Vorname, Eintritt 
FROM Person
WHERE Eintritt >= '2020-01-01';

Vergleichsoperatoren in WHERE

Die häufigsten Vergleichsoperatoren sind:

Logische Operatoren in WHERE

Mit logischen Operatoren kannst du mehrere Bedingungen kombinieren:

-- Personen aus Bern, die 2020 eingetreten sind
SELECT Name, Vorname, Eintritt, Ort
FROM Person
WHERE Ort = 'Bern' AND Eintritt >= '2020-01-01' AND Eintritt < '2021-01-01';

-- Personen aus Bern oder Zürich
SELECT Name, Vorname, Ort
FROM Person
WHERE Ort = 'Bern' OR Ort = 'Zürich';

-- Alle Personen ausser denen aus Bern
SELECT Name, Vorname, Ort
FROM Person
WHERE NOT Ort = 'Bern';  -- alternativ: WHERE Ort <> 'Bern'

Die logischen Operatoren sind:

Mustervergleich mit LIKE

Für Textsuchen kannst du den LIKE-Operator verwenden:

-- Alle Personen, deren Name mit 'M' beginnt
SELECT Name, Vorname
FROM Person
WHERE Name LIKE 'M%';

-- Alle Personen mit 'er' irgendwo im Namen
SELECT Name, Vorname
FROM Person
WHERE Name LIKE '%er%';

Die Platzhalter sind:

Ergebnisse sortieren mit ORDER BY

Mit der ORDER BY-Klausel kannst du die Reihenfolge der Ergebnisse festlegen:

-- Personen alphabetisch nach Namen sortieren
SELECT Name, Vorname, Eintritt
FROM Person
ORDER BY Name;

-- Personen nach Eintrittsdatum absteigend sortieren (neueste zuerst)
SELECT Name, Vorname, Eintritt
FROM Person
ORDER BY Eintritt DESC;

-- Personen nach Ort und innerhalb des Ortes nach Namen sortieren
SELECT Name, Vorname, Ort
FROM Person
ORDER BY Ort, Name;

Du kannst jeweils ASC (aufsteigend, Standard) oder DESC (absteigend) angeben und nach mehreren Spalten sortieren.

Ergebnisse begrenzen mit LIMIT

Wenn du nur eine bestimmte Anzahl von Zeilen zurückgeben möchtest, kannst du LIMIT verwenden:

-- Die 5 neuesten Mitglieder
SELECT Name, Vorname, Eintritt
FROM Person
ORDER BY Eintritt DESC
LIMIT 5;

Mit OFFSET kannst du auch einen Startpunkt festlegen, was für Paginierung nützlich ist:

-- Zeige Personen 11-20 in der alphabetischen Reihenfolge
SELECT Name, Vorname
FROM Person
ORDER BY Name, Vorname
LIMIT 10 OFFSET 10;  -- Überspringe die ersten 10, zeige die nächsten 10

Aggregatfunktionen

SQL bietet verschiedene Funktionen, um Berechnungen auf Datengruppen durchzuführen:

Einfache Aggregationen

-- Gesamtzahl der Personen in der Datenbank
SELECT COUNT(*) AS Anzahl_Personen
FROM Person;

-- Höchster, niedrigster und durchschnittlicher Mitgliedsbeitrag
SELECT 
    MIN(Beitrag) AS Min_Beitrag,
    MAX(Beitrag) AS Max_Beitrag,
    AVG(Beitrag) AS Durchschnitt_Beitrag
FROM Status;

-- Summe aller Spenden
SELECT SUM(Betrag) AS Gesamtspenden
FROM Spende;

Diese Funktionen reduzieren eine ganze Spalte auf einen einzelnen Wert.

Daten gruppieren mit GROUP BY

Mit GROUP BY kannst du Zeilen nach bestimmten Kriterien gruppieren und dann Aggregatfunktionen auf jede Gruppe anwenden:

-- Anzahl der Personen pro Ort
SELECT Ort, COUNT(*) AS Anzahl
FROM Person
GROUP BY Ort
ORDER BY Anzahl DESC;

-- Durchschnittliche Spende pro Sponsor
SELECT SponID, AVG(Betrag) AS Durchschnittsbetrag
FROM Spende
GROUP BY SponID
ORDER BY Durchschnittsbetrag DESC;

Gruppierte Daten filtern mit HAVING

Während WHERE vor der Gruppierung filtert, erlaubt HAVING die Filterung auf Basis von Aggregatfunktionen nach der Gruppierung:

-- Orte mit mehr als 5 Mitgliedern
SELECT Ort, COUNT(*) AS Anzahl
FROM Person
GROUP BY Ort
HAVING COUNT(*) > 5
ORDER BY Anzahl DESC;

-- Sponsoren mit Gesamtspenden über 1000 CHF
SELECT SponID, SUM(Betrag) AS Gesamtspende
FROM Spende
GROUP BY SponID
HAVING SUM(Betrag) > 1000
ORDER BY Gesamtspende DESC;

Der Unterschied zwischen WHERE und HAVING ist wichtig:

Datum- und Zeit-Funktionen

SQL bietet verschiedene Funktionen zur Arbeit mit Datums- und Zeitwerten:

-- Personen, die im Jahr 2020 eingetreten sind
SELECT Name, Vorname, Eintritt
FROM Person
WHERE EXTRACT(YEAR FROM Eintritt) = 2020;

-- Anzahl der Eintritte pro Monat
SELECT 
    EXTRACT(MONTH FROM Eintritt) AS Monat,
    COUNT(*) AS Anzahl
FROM Person
WHERE Eintritt IS NOT NULL
GROUP BY EXTRACT(MONTH FROM Eintritt)
ORDER BY Monat;

Die Funktion TO_DATE

Mit TO_DATE (in PostgreSQL) kannst du Zeichenketten in Datumswerte umwandeln:

-- Alle Eintritte nach dem 15. März 2020
SELECT Name, Vorname, Eintritt
FROM Person
WHERE Eintritt > TO_DATE('15.03.2020', 'DD.MM.YYYY');

Der zweite Parameter gibt das Format an, in dem das Datum in der Zeichenkette vorliegt.

Praktische Beispiele mit der Verein-Datenbank

Hier sind einige komplexere Beispiele, die verschiedene SELECT-Funktionen kombinieren:

-- Anzahl der Personen pro Status mit Statusbezeichnung
SELECT 
    s.Bezeichner AS Status,
    COUNT(p.PersID) AS Anzahl
FROM Person p
JOIN Status s ON p.StatID = s.StatID
GROUP BY s.StatID, s.Bezeichner
ORDER BY Anzahl DESC;

-- Durchschnittliche Anzahl Teilnehmer pro Anlass
SELECT 
    AVG(teilnehmer_count) AS Durchschnitt_Teilnehmer
FROM (
    SELECT 
        a.AnlaID,
        COUNT(t.PersID) AS teilnehmer_count
    FROM Anlass a
    LEFT JOIN Teilnehmer t ON a.AnlaID = t.AnlaID
    GROUP BY a.AnlaID
) AS anlass_stats;

Zusammenfassung

Die SELECT-Anweisung ist das vielseitigste Werkzeug in SQL und erlaubt es dir, genau die Daten zu extrahieren, die du benötigst. Durch die Kombination von Filterung (WHERE), Sortierung (ORDER BY), Begrenzung (LIMIT), Aggregation und Gruppierung (GROUP BY, HAVING) kannst du selbst komplexe Analysen durchführen.

In diesem Kapitel haben wir die grundlegenden Möglichkeiten von SELECT kennengelernt. In späteren Kapiteln werden wir fortgeschrittenere Techniken wie Joins (Verknüpfung mehrerer Tabellen) und Unterabfragen behandeln, die die Mächtigkeit von SQL noch weiter erhöhen.