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 derINSERT-Anweisung erlaubt die Verwendung von Spaltennamen statt Positionen.INSERT OR IGNORE INTO ...: die Zeilen einfügen, die nicht zu einem Konflikt durchUNIQUE- oderPRIMARY KEY-Constraints führen.INSERT OR REPLACE INTO ...: die Zeilen einfügen, die nicht zu einem Konflikt durchUNIQUE- oderPRIMARY 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:
- SQL-Klauseln kompakter und lesbarer machen:
FROM-first-Syntax mit optionalerSELECT-Klausel: DuckDB erlaubt Abfragen der FormFROM tbl, die alle Spalten auswählen (eineSELECT *-Anweisung ausführen).GROUP BY ALL: die Group-by-Spalten weglassen, indem sie aus der Attributliste derSELECT-Klausel abgeleitet werden.ORDER BY ALL: Kurzform, um nach allen Spalten zu sortieren (z. B. um deterministische Ergebnisse sicherzustellen).SELECT * EXCLUDE: die OptionEXCLUDEerlaubt das Ausschließen bestimmter Spalten aus dem*-Ausdruck.SELECT * REPLACE: die OptionREPLACEerlaubt das Ersetzen bestimmter Spalten durch andere Ausdrücke in einem*-Ausdruck.UNION BY NAME: dieUNION-Operation entlang der Spaltennamen ausführen (statt sich auf Positionen zu stützen).- Präfix-Aliase in den Klauseln
SELECTundFROM:x: 42statt42 AS xfür bessere Lesbarkeit schreiben. - Einen Prozentsatz der Tabellengröße für die
LIMIT-Klausel angeben:LIMIT 10%schreiben, um 10 % der Abfrageergebnisse zu liefern.
- Tabellen umformen:
- Variablen auf SQL-Ebene definieren:
Abfragefunktionen
- Spaltenaliase in
WHERE,GROUP BYundHAVING. (Beachten Sie, dass Spaltenaliase nicht in derON-Klausel vonJOIN-Klauseln verwendet werden können.) - Der Ausdruck
COLUMNS()kann verwendet werden, um denselben Ausdruck auf mehreren Spalten auszuführen: - Wiederverwendbare Spaltenaliase (auch „laterale Spaltenaliase“ genannt), z. B.:
SELECT i + 1 AS j, j + 2 AS k FROM range(0, 3) t(i) - Fortgeschrittene Aggregationsfunktionen für analytische (OLAP-)Abfragen:
- Kurzform
count()fürcount(*) IN-Operator für Listen und Maps- Spaltennamen für Common Table Expressions (
WITH) angeben - Spaltennamen in der
JOIN-Klausel angeben VALUESin derJOIN-Klausel verwendenVALUESim Anchor-Teil von Common Table Expressions verwendenSWITCH-Anweisungen als syntaktischer Zucker für denCASE-Ausdruck
Literale und Identifikatoren
- Unabhängigkeit von der Groß-/Kleinschreibung bei Beibehaltung der Schreibweise von Entitäten im Katalog
- Deduplizieren von Identifikatoren
- Unterstriche als Zifferntrenner in numerischen Literalen
Datentypen
Datenimport
- Automatisches Erkennen der Header und des Schemas von CSV-Dateien
- Direktes Abfragen von CSV-Dateien und Parquet-Dateien
- Replacement Scans:
- Sie können Dateien mit der Syntax
FROM 'my.csv',FROM 'my.csv.gz',FROM 'my.parquet'usw. laden. - In Python können Sie auf Pandas-Dataframes mit
FROM dfzugreifen.
- Sie können Dateien mit der Syntax
- Dateinamenserweiterung (Globbing), z. B.:
FROM 'my-data/part-*.parquet'
Funktionen und Ausdrücke
- Punkt-Operator für Function Chaining:
SELECT ('hello').upper() - String-Formatierer:
die Funktion
format()mit derfmt-Syntax und die Funktionprintf() - List Comprehensions
- List Slicing und Indizierung vom Ende (
[-1]) - String Slicing
- Notation
STRUCT.* LISTmit eckigen Klammern erzeugen- Einfaches Erzeugen von
LISTundSTRUCT - Aktualisieren des Schemas von
STRUCTs
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.grpFROM (SELECT val, grp, row_number() OVER (PARTITION BY grp ORDER BY val DESC) AS rid FROM t1 ORDER BY val DESC) AS rsWHERE rid < 4GROUP 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
- Blogbeitrag „Friendlier SQL with DuckDB“
- Blogbeitrag „Even Friendlier SQL with DuckDB“
- Blogbeitrag „SQL Gymnastics: Bending SQL into Flexible New Shapes“