Documentation Index
Fetch the complete documentation index at: https://docs.dune.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
ASOF JOIN in DuneSQL lets you join two relations based on the closest matching row according to an inequality in theON clause - typically on a timestamp or sequence field.
This is most useful when you need to:
- Get the latest price as of trade time
- Forward-fill sparse balance or config/state tables
- Enrich dense time grids (e.g. hourly/daily) from sparse event data
- Tracking actions of an ENS across addresses over time.
- Tracking actions of EIP-7702 enabled wallets by the contract they authorized to.
ASOF JOIN executes entirely at query time — it does not pre-materialize or store any helper tables. It is a runtime join optimized in the DuneSQL engine.
Syntax
Rules
- Exactly one inequality is required, comparing a right-side expression to a left-side expression using
<,<=,>, or>=. - Any number of equality predicates (left.sym = right.sym) are allowed and encouraged.
- ASOF JOIN returns only matched left rows (like INNER JOIN).
- ASOF LEFT JOIN returns all left rows and fills NULL when no neighbor exists.
Typically, expressions compare timestamps: e.g.
prices.ts <= trades.ts will pick the latest price at or before the trade.Example
Dune’s ETH balances over time
See query on dune.com.Latest price at trade time
See query on dune.com.Forward-fill with ASOF LEFT JOIN
See query on dune.com.Performance
ASOF JOIN consistently outperforms LEAD() + range joins for large temporal enrichments. Below is a rounded summary from production-scale testing (millions of rows):When to use ASOF JOIN
✅ Recommended when:- You need a point-in-time snapshot (latest state, price, config)
- You are forward-filling sparse events into a regular time spine
- Data is sparse or high-cardinality (wallet balances, token prices)
- You just need window aggregates (e.g. moving averages) → use window functions
- You already materialize reusable helper tables with valid ranges → consider pre-filled models
Limitations
- Exactly one inequality is required in the ON clause.
- Joins based on multiple inequalities are not supported — add extra conditions via equality or
WHERE.
Best Practices
- Always constrain with equality first (token, address, etc.) to avoid scanning irrelevant rows.
- Use
ASOF LEFTwhen you need to preserve all left rows, even if no match exists. - Prefer
<=or>=for clear open/closed interval intent. - Document the direction, as inequality can compare from right to left or from left to right (e.g.,
right.ts <= left.tsorleft.ts >= right.ts):<=→ “most recent up to this timestamp” (historical lookup)>=→ “next upcoming record” (future-effective lookup)