back to blogs

The SQL BETWEEN Operator: More Than Just "Syntactic Sugar"

The BETWEEN operator is one of the most common tools in a SQL developer’s kit, yet it is often the source of subtle, production-breaking bugs. From the "inclusive" trap of DATETIME stamps to handling messy strings with TRIM and LEFT, this article explores how to use BETWEEN effectively without sacrificing performance or accuracy.

Kanakadurga KunamneniKanakadurga Kunamneni|March 1, 20263 min read

If you’ve spent any time writing SQL, you’ve likely used the BETWEEN operator. It’s the "cleaner" cousin of the >= and <= combo. But beneath its readable syntax lies a few behaviors that catch even seasoned data scientists off guard—especially when shifting between numeric ranges, messy strings, and those ever-tricky timestamps.


1. The "Inclusive" Golden Rule

The most fundamental thing to remember: BETWEEN is inclusive.

When you write:

SELECT * FROM orders 
WHERE amount BETWEEN 100 AND 500;
 

SQL interprets this exactly as amount >= 100 AND amount <= 500. Both the 100 and the 500 are staying for the party. If you need to exclude the boundaries, you’ll have to revert to the standard comparison operators (> and <).

2. Handling the "Dirty" Data: TRIM and LEFT

In a perfect database, your values are sanitized. In reality, you’re often dealing with leading spaces or mixed-format strings. This is where BETWEEN needs some functional help to stay accurate.

The "Invisible Space" Trap: If you are filtering a range of product codes (e.g., 'A100' to 'A500'), a record stored as 'A150 ' (with a trailing space) might be excluded because the space changes the lexicographical weight of the string. By wrapping your column in TRIM(), you ensure the range logic only sees the actual characters: WHERE TRIM(product_id) BETWEEN 'A100' AND 'A500'.

Partial Matches: Sometimes you only care about a prefix. If you want to find all customers whose postal codes start with digits between 10 and 20, you can use LEFT(zip_code, 2) BETWEEN '10' AND '20'. This is a much cleaner way to handle category-based ranges than writing a massive LIKE or IN statement.

3. The Trap: Date vs. DateTime

This is where most production bugs are born. When you use BETWEEN on a DATE column, it works as expected. But on a DATETIME or TIMESTAMP column, the "inclusive" nature can be misleading.

Imagine you want all orders from January:

-- This might lose data!
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31';
 

In most SQL dialects, '2024-01-31' is shorthand for '2024-01-31 00:00:00'. If an order came in at 2:00 PM on the 31st, it won’t show up because it is technically "greater" than the upper bound. For time-sensitive data, many data engineers avoid BETWEEN entirely and use the "half-open" interval: WHERE order_date >= '2024-01-01' AND order_date < '2024-02-01'.

4. Sorting and Performance

One quirk that often goes unmentioned: the order of values matters. SQL expects the smaller value first. Writing BETWEEN 50 AND 10 will return zero results in most systems. If your inputs are dynamic (perhaps coming from a Python script or a dashboard filter), ensure you’ve sorted them before passing them to the query.

As for performance, BETWEEN is purely "syntactic sugar." Most modern SQL optimizers (PostgreSQL, SQL Server, Snowflake) literally rewrite your BETWEEN clause into >= AND <= during the compilation phase. You won't see a speed boost, but you do get better readability.

However, be careful with the functions we mentioned earlier. While TRIM() or LEFT() make the logic work on messy data, they can make the database "work harder" because it has to transform every single row before checking the range, which can sometimes prevent the use of an index.


Final Thoughts

The BETWEEN operator is a staple for a reason and it makes the code look less like a math equation and more like a sentence. Just remember to be extra cautious when timestamps are involved, keep your lower bounds on the left, and don't be afraid to clean your strings first.