SQL-Spickzettel (PostgreSQL)

Die Anweisungen, die du am häufigsten brauchst, mit je einem Beispiel. Die Beispiele laufen auf der Bäckerei-Übungsdatenbank und verwenden die PostgreSQL-Syntax. Andere Datenbanken unterscheiden sich in Details, die dort vermerkt sind, wo sie wichtig sind.

Lesen und filtern

SELECT wählt Spalten aus, FROM nennt die Tabelle, WHERE behält passende Zeilen, ORDER BY sortiert, LIMIT kürzt das Ergebnis. Text steht in einfachen Anführungszeichen.

SELECT name, unit_price
FROM products
WHERE category = 'pastry' AND unit_price < 3
ORDER BY unit_price DESC
LIMIT 5;

Ergebnis: Die Backwaren unter 3.00, das teuerste zuerst.

Muster, Listen, Bereiche und NULL

LIKE sucht nach Mustern (% steht für beliebig viel Text, _ für ein Zeichen; ILIKE ignoriert Groß- und Kleinschreibung). IN prüft eine Liste, BETWEEN prüft einen Bereich einschließlich der Grenzen, IS NULL findet fehlende Werte.

SELECT first_name, loyalty_tier
FROM customers
WHERE first_name LIKE 'A%' OR loyalty_tier IS NULL
ORDER BY first_name;

Ergebnis: Kunden, deren Name mit A beginnt, oder die keine Treuestufe haben.

Mit GROUP BY zusammenfassen

COUNT, SUM, AVG, MIN und MAX machen aus Zeilen je einen Wert pro Gruppe. WHERE filtert Zeilen vor der Gruppierung, HAVING filtert die Gruppen.

SELECT channel, COUNT(*) AS orders
FROM orders
GROUP BY channel
HAVING COUNT(*) > 5
ORDER BY channel;

Ergebnis: Nur der Online-Kanal mit 7 Bestellungen.

Tabellen verbinden

INNER JOIN behält Treffer, LEFT JOIN behält jede Zeile der linken Tabelle. Vergib kurze Aliase für Tabellen und verbinde immer über den Schlüssel.

SELECT p.name, SUM(oi.quantity) AS units
FROM products AS p
JOIN order_items AS oi ON oi.product_id = p.product_id
GROUP BY p.name
ORDER BY units DESC, p.name
LIMIT 3;

Ergebnis: Die drei meistverkauften Produkte.

CASE: wenn/dann in SQL

CASE gibt den Wert der ersten Bedingung zurück, die wahr ist, ähnlich wie WENNS in Excel. Ohne ELSE gibt es NULL zurück.

SELECT name,
       CASE WHEN unit_price < 3 THEN 'budget' WHEN unit_price <= 4 THEN 'standard' ELSE 'premium' END AS band
FROM products
ORDER BY product_id;

Ergebnis: Jedes Produkt mit dem Etikett budget, standard oder premium.

Unterabfragen und WITH

Eine Unterabfrage ist eine Abfrage innerhalb einer anderen. WITH gibt einer solchen einen Namen, damit du die Hauptabfrage wie eine Geschichte lesen kannst.

WITH spend AS (
  SELECT o.customer_id, SUM(oi.quantity * p.unit_price) AS total
  FROM orders AS o
  JOIN order_items AS oi ON oi.order_id = o.order_id
  JOIN products AS p ON p.product_id = oi.product_id
  GROUP BY o.customer_id
)
SELECT customer_id, total FROM spend WHERE total > 30 ORDER BY total DESC;

Ergebnis: Kunde Nr. 1 (Lopez) mit 37.10 und Kunde Nr. 3 (Dubois) mit 36.00.

Fensterfunktionen

OVER fügt eine Berechnung über Zeilen hinzu, ohne sie zusammenzufassen: Ränge, laufende Summen und LAG/LEAD für die vorherige und die nächste Zeile.

SELECT order_id, order_date,
       RANK() OVER (ORDER BY order_date) AS day_rank,
       LAG(order_date) OVER (ORDER BY order_id) AS prev_date
FROM orders
ORDER BY order_id;

Ergebnis: Jede Bestellung mit ihrem Datumsrang und dem Datum der davorliegenden Bestellung.

Daten ändern

INSERT fügt Zeilen hinzu, UPDATE ändert sie, DELETE entfernt sie. Schreibe bei UPDATE und DELETE immer ein WHERE und führe es zuerst als SELECT aus, um zu sehen, was betroffen wäre. Riskante Änderungen packst du in BEGIN und ROLLBACK.

UPDATE products
SET unit_price = unit_price + 0.10
WHERE category = 'drinks'
RETURNING name, unit_price;

Ergebnis: Die beiden Getränke mit ihren neuen Preisen.

Häufige Fragen

In welcher Reihenfolge führt SQL eine Abfrage aus?
Zuerst FROM und JOIN, dann WHERE, GROUP BY, HAVING, SELECT, ORDER BY und zuletzt LIMIT. Deshalb kann ein WHERE keinen Spaltenalias aus SELECT verwenden, ORDER BY aber schon.
Unterscheidet SQL zwischen Groß- und Kleinschreibung?
Schlüsselwörter sowie Tabellen- und Spaltennamen nicht (PostgreSQL wandelt nicht in Anführungszeichen gesetzte Namen in Kleinbuchstaben um). Textwerte schon: 'Paris' und 'paris' sind verschieden, außer du verwendest ILIKE oder LOWER().
Funktioniert das auch in MySQL, SQL Server oder SQLite?
Der Kern (SELECT, WHERE, GROUP BY, JOIN, CASE) funktioniert. Unterschiede gibt es bei LIMIT (TOP in SQL Server), bei der Textverkettung, bei Datumsfunktionen und bei RETURNING. Die Details findest du in der Dokumentation deiner Datenbank.

Übe es