Lernen  /  Leitfäden

SQL ASOF JOIN erklärt: jede Zeile dem neuesten Wert zuordnen, in jeder Engine

Wie hoch war der Preis beim Handel? Welcher Wechselkurs galt am Rechnungsdatum? Was wusste das Modell zum Zeitpunkt der Vorhersage? Das sind ASOF-Fragen, und 2026 hat fast jede Engine einen Join dafür. So funktioniert er, mit Beispielen, die wir ausgeführt haben.

Leitfaden9 Min. LesezeitAktualisiert am 9 November 2026
SQLPythonDatenanalyse
Alle Leitfäden und Spickzettel

Ein normaler Join ordnet Zeilen zu, wenn die Schlüssel gleich sind. Viele echte Fragen brauchen etwas anderes: die Zeile mit dem neuesten Zeitstempel zum oder vor einem anderen Zeitstempel. Den Aktienkurs im Moment eines Kaufs. Den Wechselkurs am Tag einer Rechnung. Den Tarif des Kunden, als er ein Support-Ticket eröffnete. Das ist ein ASOF JOIN ("as of", also "zum Stand von"). Snowflake, DuckDB, ClickHouse und Polars haben ihn, und Apache Spark hat ihn in Version 4.3 ergänzt. Dieser Leitfaden erklärt die Idee einmal und zeigt dann die Syntax in jedem Tool.

Die Idee an einem Beispiel

Wir nutzen überall dieselben zwei kleinen Tabellen. Jeder Handel soll die letzte Notierung desselben Symbols zum oder vor dem Handelszeitpunkt bekommen.

trade_idsymHandelszeitLetzte Notierung zum oder davorPreis
1A10:00:0510:00:0010.0
2A10:00:2010:00:1010.5
3B10:00:01noch keine (erste B-Notierung um 10:00:15)NULL
4B10:00:3010:00:1520.0

Beachten Sie Handel 2: Es gibt auch eine Notierung um 10:00:25, aber sie kam nach dem Handel und darf nicht verwendet werden. Und Handel 3 hat überhaupt keine frühere Notierung. Was mit ihm passiert, hängt vom Join-Typ ab, der häufigsten Fehlerquelle.

Wie ein ASOF JOIN denkt
Gleiche Schlüsselgleiches Symbol, gleicher Kunde oder gleiches Konto
Ungleichungrechte Zeit zum oder vor der linken Zeit
Genau einernur der nächste Treffer
Behalten oder verwerfenLEFT behält Zeilen ohne Treffer

Die Syntax in jeder Engine

Jedes Beispiel unten liefert die Preise 10.0, 10.5, NULL und 20.0. Die Versionen für DuckDB 2.0, Spark 4.3, Polars 2.1 und pandas 3.1 haben wir selbst ausgeführt.

SQL
SELECT t.trade_id, t.sym, t.ts, q.price
FROM trades t
ASOF JOIN quotes q
  MATCH_CONDITION (t.ts >= q.ts)
  ON t.sym = q.sym;

MATCH_CONDITION enthält die eine Ungleichung (>=, >, <= oder <); ON enthält die gleichen Schlüssel. Zeilen ohne Treffer kommen mit NULL zurück, wie bei einem Left Join.

Kein ASOF JOIN? Nutzen Sie diese Alternative

BigQuery und PostgreSQL haben kein ASOF-Schlüsselwort, aber zwei Muster liefern dieselbe Antwort. In unseren Tests lieferten beide identische Ergebnisse wie die ASOF-Versionen.

QUALIFY

BigQuery und die meisten
Idee
alle früheren Notierungen joinen, dann die letzte pro Handel behalten
  • Kurz und gut lesbar
  • Baut zuerst alle früheren Treffer auf und kann bei großen Tabellen langsam sein

Gut für Tausende bis Millionen Zeilen.

LATERAL

Am besten in PostgreSQL
Idee
für jeden Handel eine Zeile mit ORDER BY und LIMIT 1 nachschlagen
  • Nutzt in PostgreSQL einen Index auf (sym, ts) und skaliert gut
  • In BigQuery nicht unterstützt

Die beste Option in PostgreSQL.

SQL
-- QUALIFY version (WHERE TRUE is harmless and keeps BigQuery happy,
-- which has long asked for WHERE, GROUP BY or HAVING next to QUALIFY)
SELECT t.trade_id, q.price
FROM trades t
LEFT JOIN quotes q
  ON q.sym = t.sym AND q.ts <= t.ts
WHERE TRUE
QUALIFY ROW_NUMBER() OVER (PARTITION BY t.trade_id ORDER BY q.ts DESC) = 1;

-- LATERAL version (PostgreSQL)
SELECT t.trade_id, q.price
FROM trades t
LEFT JOIN LATERAL (
  SELECT price FROM quotes q
  WHERE q.sym = t.sym AND q.ts <= t.ts
  ORDER BY q.ts DESC
  LIMIT 1
) q ON TRUE;

Vier Fehler, die Sie vermeiden sollten

  1. 1

    Versehentlich Zeilen verlieren

    Prüfen Sie, ob der einfache ASOF JOIN Ihrer Engine ein Inner Join ist. In DuckDB, ClickHouse und Spark schreiben Sie LEFT, wenn jede linke Zeile erhalten bleiben muss.

  2. 2

    Die falsche Richtung

    ">=" bedeutet den letzten Wert zum oder davor; "<=" den nächsten Wert zum oder danach. pandas nennt das backward und forward; Polars spricht von Strategien.

  3. 3

    Zu alte Werte zuordnen

    Eine Notierung von gestern ist immer noch "die letzte". Fügen Sie in pandas oder Polars eine Toleranz hinzu oder in SQL einen Filter wie t.ts - q.ts <= INTERVAL 1 HOUR.

  4. 4

    Die gleichen Schlüssel vergessen

    Ohne ON t.sym = q.sym kann ein Handel in A eine Notierung von B bekommen.

Zeitlich korrekt
Nur Daten verwenden, die zum betrachteten Zeitpunkt existierten.
Rückwärtszuordnung
Die letzte rechte Zeile zum oder vor der linken Zeile; der Standard in den meisten Tools.
Vorwärtszuordnung
Die erste rechte Zeile zum oder nach der linken Zeile, etwa die nächste Lieferung nach einer Bestellung.
Toleranz
Der größte erlaubte Abstand zwischen den beiden Zeiten; ältere Treffer liefern NULL.

Testen Sie Ihr Wissen

1/3Was liefert ein ASOF JOIN für jede linke Zeile?

2/3Was passiert in DuckDB mit Trades ohne frühere Notierung, wenn Sie ASOF JOIN ohne LEFT schreiben?

3/3BigQuery hat keinen ASOF JOIN. Was ist eine funktionierende Alternative?

Mehr SQL: SQL-Joins erklärt, Fensterfunktionen erklärt und der SQL-Spickzettel. Zu den Tools: Neu in Polars 2.1 und DuckDB 2.0.

Quellen: Snowflake-Dokumentation zu ASOF JOIN; Dokumentation von DuckDB, ClickHouse, pandas (merge_asof) und Polars (join_asof); Release Notes zu Apache Spark 4.3.0 (30. Oktober 2026). Beispiele getestet mit DuckDB 2.0.0, PySpark 4.3.0, Polars 2.1.0 und pandas 3.1.0; die Syntax für Snowflake, ClickHouse, BigQuery und PostgreSQL folgt deren Dokumentation.

Alessandro Ecclesie AgazziGeschrieben von Alessandro Ecclesie Agazzi, Analytics Engineer in London. Aktualisiert am 9 November 2026. Über mich

War das hilfreich?

Hier erscheinen regelmäßig neue Leitfäden und Artikel zu Neuigkeiten rund um Daten und KI. Folgen Sie mir auf LinkedIn oder teilen Sie diesen Artikel mit Kollegen.