Skip to main content

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
BETWEEN tests whether a value falls in a range. It is shorthand for a pair of comparisons, and it is the clause people most often get subtly wrong on dates. Open the client with mysql -u root -p sakila before you start.

How BETWEEN works

Replace LOW_BOUND and HIGH_BOUND with the 2 ends of the range. x BETWEEN a AND b means x >= a AND x <= b. The range includes both bounds, and you write the low bound first.

Examples

1) A range of numbers

Films of exactly 60 minutes are in the result, which shows that the low bound counts as a match.

2) The same thing written out

Identical rows. BETWEEN saves you naming the column twice and nothing else.

3) Outside the range

NOT BETWEEN keeps rows below the low bound and above the high bound. 46 minutes is the shortest film in the catalog.

The low bound has to come first

BETWEEN does not sort your bounds for you. Give it a high value first and it asks for numbers that are both at least 70 and at most 60, which no number is.
No error and no warning. An empty result from a range you expected to match is worth checking for swapped bounds first.

BETWEEN on dates stops at midnight

This is the one that costs people real time, and it starts with the column’s type.
payment_date is a datetime, so every value carries a time of day. A date written without a time means midnight at the start of that day.
That reads as “the 25th and the 26th” and returns 137 rows. Asking for the same 2 days as a half-open range returns 311.
The high bound '2005-05-26' became 2005-05-26 00:00:00. Every payment taken during the 26th is later than that instant, so BETWEEN excluded all of them. The 137 rows are the 25th on its own, and they would have included a payment landing exactly on the stroke of midnight if one existed. Write a date range as >= start AND < the day after the end. That form needs no thought about whether the column carries a time, and it stays correct if the column later gains one.

Summary

  • Use BETWEEN for a range, and expect it to include both bounds.
  • Write the low bound first, because a reversed range matches nothing and says nothing.
  • Read x BETWEEN a AND b as x >= a AND x <= b.
  • Use >= start AND < day_after_end for dates rather than BETWEEN.

See also