Zum Inhalt springen

Friendly SQL

DuckDB bietet mehrere fortgeschrittene SQL-Funktionen und syntaktischen Zucker, um SQL-Abfragen knapper zu machen. Wir bezeichnen das umgangssprachlich als „Friendly SQL“.

Mehrere dieser Funktionen wurden zuerst von DuckDB eingeführt, andere sind von anderen Systemen inspiriert. Viele der ursprünglich von DuckDB eingeführten Funktionen (z. B. GROUP BY ALL) wurden inzwischen von anderen Systemen übernommen.

Tipp Es gibt einen Friendly-SQL-Kalender 2026 mit einer kurzen Erklärung, einem Beispiel und einer abstrakten Illustration für 12 Friendly-SQL-Funktionen.

Klauseln

  • Tabellen anlegen und Daten einfügen:
    • CREATE OR REPLACE TABLE: DROP TABLE IF EXISTS-Anweisungen in Skripten vermeiden.
    • CREATE TABLE ... AS SELECT (CTAS): eine neue Tabelle aus der Ausgabe einer Tabelle anlegen, ohne das Schema manuell zu definieren.
    • INSERT INTO ... BY NAME: diese Variante der INSERT-Anweisung erlaubt die Verwendung von Spaltennamen statt Positionen.
    • INSERT OR IGNORE INTO ...: die Zeilen einfügen, die nicht zu einem Konflikt durch UNIQUE- oder PRIMARY KEY-Constraints führen.
    • INSERT OR REPLACE INTO ...: die Zeilen einfügen, die nicht zu einem Konflikt durch UNIQUE- oder PRIMARY KEY-Constraints führen. Bei denen, die zu einem Konflikt führen, die Spalten der vorhandenen Zeile durch die neuen Werte der einzufügenden Zeile ersetzen.
  • Tabellen beschreiben und Statistiken berechnen:
    • DESCRIBE: liefert eine knappe Zusammenfassung des Schemas einer Tabelle oder Abfrage.
    • SUMMARIZE: liefert Zusammenfassungsstatistiken für eine Tabelle oder Abfrage.
  • SQL-Klauseln kompakter und lesbarer machen:
  • Tabellen umformen:
    • PIVOT, um lange Tabellen in breite Tabellen zu verwandeln.
    • UNPIVOT, um breite Tabellen in lange Tabellen zu verwandeln.
  • Variablen auf SQL-Ebene definieren:

Abfragefunktionen

Literale und Identifikatoren

Datentypen

Datenimport

Funktionen und Ausdrücke

Join-Typen

Nachgestellte Kommas

DuckDB erlaubt nachgestellte Kommas, sowohl beim Auflisten von Entitäten (z. B. Spalten- und Tabellennamen) als auch beim Konstruieren von LIST-Elementen. Die folgende Abfrage funktioniert beispielsweise:

SELECT
42 AS x,
['a', 'b', 'c',] AS y,
'hello world' AS z,
;

Abfragen „Top-N in Gruppe“

Das Berechnen der „Top-N-Zeilen in einer Gruppe“, geordnet nach bestimmten Kriterien, ist eine häufige Aufgabe in SQL, die leider oft eine komplexe Abfrage mit Fensterfunktionen und/oder Unterabfragen erfordert.

Zur Unterstützung stellt DuckDB die Aggregatfunktionen max(arg, n), min(arg, n), arg_max(arg, val, n), arg_min(arg, val, n), max_by(arg, val, n) und min_by(arg, val, n) bereit, um effizient die „obersten“ n Zeilen in einer Gruppe anhand einer bestimmten Spalte in aufsteigender oder absteigender Reihenfolge zu liefern.

Verwenden wir beispielsweise die folgende Tabelle:

SELECT * FROM t1;
┌─────────┬───────┐
│ grp │ val │
│ varchar │ int32 │
├─────────┼───────┤
│ a │ 2 │
│ a │ 1 │
│ b │ 5 │
│ b │ 4 │
│ a │ 3 │
│ b │ 6 │
└─────────┴───────┘

Wir möchten eine Liste der Top-3-val-Werte in jeder Gruppe grp erhalten. Die herkömmliche Art, das zu tun, ist eine Fensterfunktion in einer Unterabfrage:

SELECT array_agg(rs.val), rs.grp
FROM
(SELECT val, grp, row_number() OVER (PARTITION BY grp ORDER BY val DESC) AS rid
FROM t1 ORDER BY val DESC) AS rs
WHERE rid < 4
GROUP BY rs.grp;
┌───────────────────┬─────────┐
│ array_agg(rs.val) │ grp │
│ int32[] │ varchar │
├───────────────────┼─────────┤
│ [3, 2, 1] │ a │
│ [6, 5, 4] │ b │
└───────────────────┴─────────┘

In DuckDB können wir das viel knapper (und effizienter!) tun:

SELECT max(val, 3) FROM t1 GROUP BY grp;
┌─────────────┐
│ max(val, 3) │
│ int32[] │
├─────────────┤
│ [3, 2, 1] │
│ [6, 5, 4] │
└─────────────┘

Verwandte Blogbeiträge