BETWEEN
The BETWEEN operator tests whether a value falls within an inclusive range, equivalent to combining two comparisons with AND.
Overview
expr BETWEEN low AND high is shorthand for expr >= low AND expr <= high -- it's inclusive on both ends. It works with numbers, dates, timestamps, and any other orderable type, and it reads more naturally than the equivalent compound condition for simple range checks.
Copy code
SELECT order_id, order_total
FROM orders
WHERE order_total BETWEEN 50 AND 200;
SELECT event_name, event_date
FROM events
WHERE event_date BETWEEN DATE '2026-01-01' AND DATE '2026-03-31';
NOT BETWEEN
Negating the range is just as readable:
Copy code
SELECT * FROM orders WHERE order_total NOT BETWEEN 50 AND 200;
Common pitfall: date ranges
A frequent mistake is using BETWEEN with a bare date on one side and a TIMESTAMP column on the other, expecting it to cover the whole end day. col BETWEEN '2026-01-01' AND '2026-01-31' on a TIMESTAMP column effectively means ... AND '2026-01-31 00:00:00', silently excluding any timestamps later in that final day. The safer pattern is an explicit half-open range:
Copy code
SELECT * FROM events
WHERE event_ts >= TIMESTAMP '2026-01-01 00:00:00'
AND event_ts < TIMESTAMP '2026-02-01 00:00:00';
BETWEEN SYMMETRIC (DuckDB)
DuckDB supports BETWEEN SYMMETRIC, which works even if the "low" and "high" bounds are supplied in the wrong order -- it automatically treats whichever value is smaller as the lower bound:
Copy code
SELECT 5 BETWEEN SYMMETRIC 10 AND 1; -- TRUE, equivalent to 5 BETWEEN 1 AND 10
Performance
Because BETWEEN decomposes into two comparisons, it can use the same indexes or zone-map pruning that a range scan on >=/<= would use -- there's no performance penalty for using BETWEEN over the equivalent AND expression.
Related terms
The IN operator tests whether a value matches any value in a given list or subquery, providing a concise alternative to multiple OR conditions.
LIKE operator →The LIKE operator performs pattern matching on string values, using % as a wildcard for any number of characters and _ for a single character.
FAQS
Inclusive on both ends -- col BETWEEN a AND b is equivalent to col >= a AND col <= b.
If the column is a TIMESTAMP and the upper bound is a bare date like '2026-01-31', it's interpreted as midnight at the start of that day, excluding any later timestamps on the 31st; use an explicit half-open range with < the next day instead.
It allows the two bounds to be given in either order, automatically using the smaller as the lower bound and the larger as the upper bound, unlike plain BETWEEN which requires low AND high in that order.
