Suchen

Tutorial · Programmierung & Entwicklung

SQL lernen: Daten abfragen mit SELECT, WHERE und JOIN

Mit SELECT wählst du Spalten aus, mit WHERE filterst du Zeilen und mit JOIN verbindest du Tabellen. Alle Abfragen in diesem Artikel kannst du ohne Datenbankserver nachvollziehen: SQLite steckt in jeder Python-Installation.

Wand aus beschrifteten Holzschubladen eines Karteischranks

Das Wichtigste in Kürze

  • Eine Abfrage nennt mit SELECT die Spalten, mit FROM die Tabelle und mit WHERE die Bedingungen für die Zeilen.
  • Fehlende Werte (NULL) findest du nur mit IS NULL, nicht mit = NULL.
  • Ohne ORDER BY ist die Reihenfolge der Ergebniszeilen nicht festgelegt.
  • JOIN liefert nur Zeilen mit Treffer auf beiden Seiten, LEFT JOIN behält alle Zeilen der linken Tabelle und füllt fehlende Werte mit NULL.

Üben ohne Installation: SQLite über Python

SQL (Structured Query Language) ist die Sprache, mit der du Daten aus relationalen Datenbanken abfragst. Daten liegen dort in Tabellen aus Zeilen und Spalten; Tabellen können über gemeinsame Werte aufeinander verweisen.

Zum Üben brauchst du keinen Datenbankserver. Python bringt das Modul sqlite3 mit, und mit dem Namen ":memory:" legt es laut Python-Dokumentation eine Datenbank an, die nur im Arbeitsspeicher existiert. Das folgende Skript erstellt zwei ausgedachte Tabellen: kunden und bestellungen. Eine Bestellung verweist über kunden_id auf einen Kunden. Wie du Python installierst und Skripte startest, steht in den Python-Grundlagen.

Python
import sqlite3

con = sqlite3.connect(":memory:")
con.executescript("""
CREATE TABLE kunden (
  id     INTEGER PRIMARY KEY,
  name   TEXT NOT NULL,
  email  TEXT,
  status TEXT
);
CREATE TABLE bestellungen (
  bestellnummer INTEGER PRIMARY KEY,
  kunden_id     INTEGER REFERENCES kunden(id),
  betrag        REAL,
  status        TEXT
);
INSERT INTO kunden VALUES
  (1, 'Marta Beispiel', 'marta@example.com', 'aktiv'),
  (2, 'Malte Muster',   'malte@example.org', 'aktiv'),
  (3, 'Jonas Probe',    'jonas@example.com', 'inaktiv'),
  (4, 'Lea Platzhalter', NULL,               'aktiv');
INSERT INTO bestellungen VALUES
  (1001, 1, 120.00, 'offen'),
  (1002, 1,  45.50, 'versendet'),
  (1003, 2, 210.00, 'versendet'),
  (1004, 3,  80.00, 'offen'),
  (1005, NULL, 60.00, 'offen');
""")

def zeige(sql):
    cur = con.execute(sql)
    print(" | ".join(d[0] for d in cur.description))
    for zeile in cur:
        print(" | ".join("NULL" if w is None else str(w) for w in zeile))

zeige("SELECT name, email FROM kunden;")

Speichere das Skript als uebung.py und starte es. Für jede weitere Abfrage in diesem Artikel ersetzt du den Text in der letzten Zeile.

SELECT: Spalten auswählen

Die einfachste Abfrage nennt Spalten und Tabelle:

SQL
SELECT name, email
FROM kunden;
Text
name | email
Marta Beispiel | marta@example.com
Malte Muster | malte@example.org
Jonas Probe | jonas@example.com
Lea Platzhalter | NULL

SELECT bestimmt die Spalten, FROM die Tabelle. Das Semikolon schließt die Anweisung ab. Schlüsselwörter werden oft großgeschrieben, damit sie sich von Tabellen- und Spaltennamen abheben; nötig ist das nicht. Bei Lea fehlt die E-Mail-Adresse: Die Datenbank speichert dort NULL, also „kein Wert".

Mit SELECT * bekommst du alle Spalten. Für gezielte Abfragen ist es übersichtlicher, die Spalten ausdrücklich zu nennen: So siehst du schon im Code, welche Daten du abrufst.

Spalten umbenennen mit AS

Mit AS gibst du einer Spalte im Ergebnis einen anderen Namen (Alias). Die Tabelle selbst bleibt unverändert:

SQL
SELECT name AS kundenname,
       email AS kontaktadresse
FROM kunden;

Aliasnamen ohne Leerzeichen sind am unkompliziertesten; für Namen mit Leerzeichen brauchst du je nach Datenbank besondere Anführungszeichen.

WHERE: Zeilen filtern

WHERE legt Bedingungen fest. Zurück kommen nur Zeilen, die sie erfüllen:

SQL
SELECT bestellnummer, betrag
FROM bestellungen
WHERE betrag > 100;
Text
bestellnummer | betrag
1001 | 120.0
1003 | 210.0

Neben > gibt es = (gleich), < (kleiner), <= (kleiner oder gleich) und >= (größer oder gleich). Für „ungleich" akzeptiert SQLite laut Dokumentation sowohl <> als auch !=. Textwerte stehen in einfachen Anführungszeichen, Zahlen ohne:

SQL
SELECT bestellnummer, status
FROM bestellungen
WHERE status = 'offen';

Ein falsch geschriebener Spaltenname führt zu einer Fehlermeldung statt zu einem Ergebnis.

Bedingungen kombinieren

Mit AND müssen alle Bedingungen zutreffen, mit OR genügt eine. Mischst du beide, setze Klammern, damit klar ist, was zusammengehört:

SQL
SELECT bestellnummer, status
FROM bestellungen
WHERE status = 'offen'
   OR (status = 'versendet' AND betrag > 100);
Text
bestellnummer | status
1001 | offen
1003 | versendet
1004 | offen
1005 | offen

Alle offenen Bestellungen sind dabei, von den versendeten nur die über 100.

Textmuster, Wertebereiche und fehlende Werte

LIKE sucht nach Mustern. % steht für beliebig viele Zeichen, _ für genau eines:

SQL
SELECT name
FROM kunden
WHERE name LIKE 'Ma%';
Text
name
Marta Beispiel
Malte Muster

In SQLite unterscheidet LIKE standardmäßig nicht zwischen Groß- und Kleinschreibung, allerdings nur bei ASCII-Buchstaben; Umlaute behandelt es laut Dokumentation anders. Andere Datenbanken verhalten sich hier unterschiedlich.

BETWEEN fragt einen Bereich ab, die Grenzen eingeschlossen. betrag BETWEEN 50 AND 150 entspricht betrag >= 50 AND betrag <= 150:

SQL
SELECT bestellnummer, betrag
FROM bestellungen
WHERE betrag BETWEEN 50 AND 150;

Ein Sonderfall sind fehlende Werte. kunden_id = NULL findet nichts, weil ein Vergleich mit NULL selbst NULL ergibt und nicht „wahr". Verwende IS NULL oder IS NOT NULL:

SQL
SELECT bestellnummer
FROM bestellungen
WHERE kunden_id IS NULL;
Text
bestellnummer
1005

Mit = NULL statt IS NULL liefert dieselbe Abfrage nur die Kopfzeile, ohne einen einzigen Treffer.

Sortieren und begrenzen: ORDER BY und LIMIT

Ohne ORDER BY ist die Reihenfolge der Ergebniszeilen nicht festgelegt. Mit ORDER BY sortierst du, standardmäßig aufsteigend; DESC dreht die Richtung um. LIMIT begrenzt die Zahl der Zeilen:

SQL
SELECT bestellnummer, betrag
FROM bestellungen
ORDER BY betrag DESC
LIMIT 3;
Text
bestellnummer | betrag
1003 | 210.0
1001 | 120.0
1004 | 80.0

Zählen und summieren: COUNT, SUM und GROUP BY

Aggregatfunktionen fassen viele Zeilen zu einem Wert zusammen: COUNT(*) zählt Zeilen, SUM() addiert, AVG() bildet den Durchschnitt. Mit GROUP BY rechnest du das für jede Gruppe getrennt aus:

SQL
SELECT status, COUNT(*) AS anzahl, SUM(betrag) AS umsatz
FROM bestellungen
GROUP BY status
ORDER BY status;
Text
status | anzahl | umsatz
offen | 3 | 260.0
versendet | 2 | 255.5

Genau so entstehen viele Kennzahlen im Marketing, etwa Anfragen pro Monat; ein Beispiel dafür steht im Artikel zu Marketing-KPIs.

JOIN: Tabellen verbinden

In relationalen Datenbanken liegen zusammengehörige Informationen in verschiedenen Tabellen. Ein JOIN führt passende Zeilen über eine gemeinsame Spalte zusammen. Mit kurzen Aliasnamen für die Tabellen bleibt die Abfrage lesbar:

SQL
SELECT k.name, b.bestellnummer
FROM kunden AS k
JOIN bestellungen AS b
  ON k.id = b.kunden_id
ORDER BY b.bestellnummer;
Text
name | bestellnummer
Marta Beispiel | 1001
Marta Beispiel | 1002
Malte Muster | 1003
Jonas Probe | 1004

ON beschreibt die Verknüpfung: Die id des Kunden muss zur kunden_id der Bestellung passen. Die Präfixe k. und b. zeigen, aus welcher Tabelle eine Spalte stammt. Das ist Pflicht, sobald beide Tabellen gleichnamige Spalten haben, hier etwa status.

INNER JOIN und LEFT JOIN

Ein einfacher JOIN ist ein INNER JOIN; laut SQLite-Dokumentation sind beide Schreibweisen dort völlig gleichwertig. Er liefert nur Zeilen, für die es auf beiden Seiten einen Treffer gibt. Deshalb fehlen oben Lea, die nichts bestellt hat, und Bestellung 1005 ohne Kunden.

LEFT JOIN behält dagegen alle Zeilen der linken Tabelle. Gibt es rechts keinen Treffer, stehen in den Spalten der rechten Tabelle NULL-Werte:

SQL
SELECT k.name, b.bestellnummer
FROM kunden AS k
LEFT JOIN bestellungen AS b
  ON k.id = b.kunden_id
ORDER BY k.id, b.bestellnummer;
Text
name | bestellnummer
Marta Beispiel | 1001
Marta Beispiel | 1002
Malte Muster | 1003
Jonas Probe | 1004
Lea Platzhalter | NULL

Welche Variante passt, hängt von der Frage ab. Geht es nur um vorhandene Bestellungen, reicht JOIN. Sollen alle Kunden erscheinen, auch die ohne Bestellung, brauchst du LEFT JOIN. Zusammen mit GROUP BY zählst du so die Bestellungen je Kunde, einschließlich der Nullen:

SQL
SELECT k.name, COUNT(b.bestellnummer) AS bestellungen
FROM kunden AS k
LEFT JOIN bestellungen AS b
  ON k.id = b.kunden_id
GROUP BY k.id, k.name
ORDER BY bestellungen DESC, k.name;
Text
name | bestellungen
Marta Beispiel | 2
Jonas Probe | 1
Malte Muster | 1
Lea Platzhalter | 0

COUNT(b.bestellnummer) zählt nur Werte, die nicht NULL sind; deshalb steht bei Lea eine 0.

Abfragen schrittweise aufbauen

Die Bausteine lassen sich kombinieren. Diese Abfrage zeigt die Bestellungen aktiver Kunden mit Namen:

SQL
SELECT k.name, b.bestellnummer, b.betrag
FROM kunden AS k
JOIN bestellungen AS b
  ON k.id = b.kunden_id
WHERE k.status = 'aktiv'
ORDER BY b.bestellnummer;

Geschrieben wird in der Reihenfolge SELECT, FROM, JOIN, WHERE, GROUP BY, ORDER BY, LIMIT. Beim Entwickeln gehst du am besten anders herum vor: erst Tabelle und Spalten, dann die Verknüpfung, dann die Filter, zuletzt Gruppierung und Sortierung. Prüfe nach jedem Schritt, ob das Ergebnis zur Frage passt. So erkennst du sofort, welcher Baustein ein unerwartetes Ergebnis verursacht; mehr zu dieser Arbeitsweise findest du unter Debugging für Einsteiger.

Praxis-Tipp: Die Grundformen gelten fast überall, Details wie Datumsfunktionen oder Textvergleiche unterscheiden sich aber zwischen Datenbanksystemen. Wenn eine Abfrage in deinem System anders reagiert als in SQLite, schau zuerst in dessen Dokumentation.

Dein nächster Schritt

Erweitere das Übungsskript um eine dritte Tabelle, zum Beispiel kampagnen, und gib jeder Bestellung eine kampagnen_id. Schreibe dann eine Abfrage, die den Umsatz je Kampagne zeigt, und eine zweite, die auch Kampagnen ohne Bestellung auflistet. Wenn dich interessiert, wie die Daten im Browser aussehen, bevor sie in einer Datenbank landen, fang mit HTML lernen an; alle Grundlagen findest du im Ressort Programmierung.

Häufige Fragen

Kann eine SELECT-Abfrage Daten verändern?

Nein, SELECT liest nur. Zum Einfügen, Ändern und Löschen gibt es eigene Anweisungen (INSERT, UPDATE, DELETE); ob du sie ausführen darfst, hängt von den Rechten in der jeweiligen Datenbank ab.

Muss jede SQL-Anweisung mit einem Semikolon enden?

Das hängt vom Werkzeug ab. Viele erwarten es als Abschluss, manche Oberflächen führen eine einzelne Anweisung auch ohne aus. Gewöhne es dir an: Bei mehreren Anweisungen hintereinander ist es nötig.

Ist SQL in jeder Datenbank gleich?

Die Grundformen wie SELECT, WHERE, GROUP BY und JOIN sind weit verbreitet, Funktionen, Datumsbehandlung und Regeln für Textvergleiche unterscheiden sich aber. Funktioniert eine Abfrage in deinem System nicht, ist dessen Dokumentation die erste Anlaufstelle.

Quellen

  1. SELECT SQLite-Dokumentation (sqlite.org) · abgerufen am 13. November 2026
  2. SQL Language Expressions SQLite-Dokumentation (sqlite.org) · abgerufen am 13. November 2026
  3. sqlite3 — DB-API 2.0 interface for SQLite databases Python-Dokumentation (python.org) · abgerufen am 13. November 2026