SQLab Hub
Lesson 37 · BETWEEN
Lesson 37 · More Topics

SQL BETWEEN: Filter a Range of Numbers, Dates or Text

The SQL BETWEEN operator selects values inside a range, and both ends of the range are included. price BETWEEN 100 AND 200 means exactly the same as price >= 100 AND price <= 200.

↔ Inclusive ranges ▶ Runnable Playground examples 🧪 4 practice exercises 📝 5-question quiz ⏱ ~12 min

What Is SQL BETWEEN?

BETWEEN is used in a WHERE clause to keep rows whose value falls inside a range. This query lists products priced from 100 to 200:

SQLite · runs in the Playground
SELECT name, category, price
FROM products
WHERE price BETWEEN 100 AND 200
ORDER BY price
LIMIT 6;

▶ Run this query in the SQL Playground

Products priced between 100 and 200
namecategoryprice
Artisan Hot Sauce TrioFood & Beverage104.33
Smart ThermostatHome & Garden115.69
A5 Hardcover Notebook 3pkOffice Supplies123.26
Play Kitchen DeluxeToys154.36
Hydrating Face MoisturizerHealth & Beauty160.75
Zero to One (Thiel)Books163.35
✓ 6 rows · real output from the Playground database
SQL · syntax
SELECT columns
FROM table_name
WHERE column_name BETWEEN low_value AND high_value;

The lower value is written first. BETWEEN works with numbers, dates and text.

BETWEEN Includes Both Ends

BETWEEN is shorthand for two comparisons joined with AND. Counting the same range both ways gives the same answer:

SQLite · runs in the Playground
SELECT
  (SELECT COUNT(*) FROM products WHERE price BETWEEN 100 AND 200) AS with_between,
  (SELECT COUNT(*) FROM products WHERE price >= 100 AND price <= 200) AS with_comparisons;

▶ Run this query in the SQL Playground

The same range counted with BETWEEN and with comparisons
with_betweenwith_comparisons
77
✓ 1 row · real output from the Playground database

Both columns show 7. A product priced at exactly 100 or exactly 200 is included in either version.

BETWEEN With Dates

Date ranges are the most common use. This query counts the orders placed in the first quarter of 2024 and adds up their value:

SQLite · runs in the Playground
SELECT COUNT(*) AS orders,
       ROUND(SUM(total), 2) AS revenue
FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-03-31';

▶ Run this query in the SQL Playground

Orders and revenue in the first quarter of 2024
ordersrevenue
2249866.49
✓ 1 row · real output from the Playground database
Watch out when the column stores a time as well as a date. BETWEEN '2024-01-01' AND '2024-03-31' stops at midnight at the start of 31 March, so rows from later that day are left out. For date-time columns use a half-open range instead: order_time >= '2024-01-01' AND order_time < '2024-04-01'. In the Playground, order_date holds a date only, so BETWEEN is safe.

NOT BETWEEN

NOT BETWEEN returns the rows outside the range. Here it finds salaries below 60,000 or above 150,000:

SQLite · runs in the Playground
SELECT first_name, last_name, department, salary
FROM employees
WHERE salary NOT BETWEEN 60000 AND 150000
ORDER BY salary DESC
LIMIT 6;

▶ Run this query in the SQL Playground

Employees whose salary is outside 60,000 to 150,000
first_namelast_namedepartmentsalary
StevenNguyenMarketing204449
NancyThompsonCustomer Success203999
JohnLeeOperations203467
DonnaJohnsonEngineering199029
MatthewWilsonMarketing196530
PaulRobinsonFinance196032
✓ 6 rows · real output from the Playground database

Because BETWEEN includes both ends, NOT BETWEEN excludes them: a salary of exactly 60,000 is not returned.

BETWEEN With Text

With text, BETWEEN compares values in alphabetical order. That makes the upper end easy to get wrong. Which initials does this range return?

SQLite · runs in the Playground
SELECT DISTINCT SUBSTR(last_name, 1, 1) AS initial
FROM employees
WHERE last_name BETWEEN 'A' AND 'C'
ORDER BY initial;

▶ Run this query in the SQL Playground

First letters of the last names returned by BETWEEN A AND C
initial
A
B
✓ 2 rows · real output from the Playground database

A name such as "Clark" sorts after the single letter "C", so it falls outside the range. To include every name that starts with C, extend the upper bound (BETWEEN 'A' AND 'Cz') or, more clearly, use last_name >= 'A' AND last_name < 'D'.

Common BETWEEN Mistakes

Three ways a BETWEEN filter returns the wrong rows.

1. Writing the larger value first

❌ Returns no rows
SQL
SELECT name, price
FROM products
WHERE price BETWEEN 200 AND 100;
✅ Lower value first
SQL
SELECT name, price
FROM products
WHERE price BETWEEN 100 AND 200;

BETWEEN 200 AND 100 asks for values that are at least 200 and at most 100, which is impossible, so the result is empty and no error is raised. (PostgreSQL offers BETWEEN SYMMETRIC, which accepts either order.)

2. Using a date as the end of a date-time range

❌ Misses most of the last day
SQL
WHERE created_at BETWEEN '2024-03-01'
                     AND '2024-03-31'
✅ Half-open range
SQL
WHERE created_at >= '2024-03-01'
  AND created_at <  '2024-04-01'

When the column holds a timestamp, the end value is read as midnight, so everything after 00:00 on the last day is excluded.

3. Expecting BETWEEN to exclude the ends

❌ Includes 18 and 65
SQL
WHERE age BETWEEN 18 AND 65
✅ Strictly between
SQL
WHERE age > 18 AND age < 65

BETWEEN always includes both boundary values. When a boundary must be left out, write the comparisons yourself.

Practice BETWEEN Queries

4 exercises on the real Playground tables.

Write each query yourself first. Every solution has been run against the Playground database.

  1. 1Easy How many products have a rating from 4.0 to 4.5? Table: products

    Show solution
    SQLite · runs in the Playground
    SELECT COUNT(*) AS products
    FROM products
    WHERE rating BETWEEN 4.0 AND 4.5;

    ▶ Run this query in the SQL Playground

    Both 4.0 and 4.5 are included in the range.

  2. 2Easy List employees hired during 2022, earliest first. Show ten rows. Table: employees

    Show solution
    SQLite · runs in the Playground
    SELECT first_name, last_name, hire_date
    FROM employees
    WHERE hire_date BETWEEN '2022-01-01' AND '2022-12-31'
    ORDER BY hire_date
    LIMIT 10;

    ▶ Run this query in the SQL Playground

    hire_date stores a date with no time, so the last day of the year is fully included.

  3. 3Medium Count orders with a total outside the range 100 to 1,000, grouped by status. Table: orders

    Show solution
    SQLite · runs in the Playground
    SELECT status, COUNT(*) AS orders
    FROM orders
    WHERE total NOT BETWEEN 100 AND 1000
    GROUP BY status
    ORDER BY orders DESC;

    ▶ Run this query in the SQL Playground

    NOT BETWEEN keeps totals below 100 or above 1,000; GROUP BY then counts them per status.

  4. 4Medium Find orders placed in December 2024 with a total between 500 and 2,000. Table: orders

    Show solution
    SQLite · runs in the Playground
    SELECT id, order_date, total
    FROM orders
    WHERE order_date BETWEEN '2024-12-01' AND '2024-12-31'
      AND total BETWEEN 500 AND 2000
    ORDER BY order_date, id;

    ▶ Run this query in the SQL Playground

    Two BETWEEN conditions joined with AND: one for the date range and one for the amount.

📝 Quiz — BETWEEN

Test your understanding · 0/5 answered

Question 1 of 5

Which rows does "price BETWEEN 10 AND 20" return?

Question 2 of 5

What does "price BETWEEN 20 AND 10" return in most databases?

Question 3 of 5

A column stores timestamps. Which filter returns all of March 2024?

Question 4 of 5

How do you select values outside a range?

Question 5 of 5

Does last_name BETWEEN 'A' AND 'C' return the name 'Clark'?

BETWEEN Interview Questions

Q1. Is BETWEEN inclusive or exclusive?

Inclusive at both ends. x BETWEEN a AND b is equivalent to x >= a AND x <= b.

Q2. Why can BETWEEN be risky with date-time columns?

A date written without a time is treated as midnight. Used as the upper bound, it excludes the rest of that day. A half-open range, >= start AND < next_day, avoids the problem.

Q3. How does BETWEEN treat NULL?

If the tested value or either bound is NULL, the result is unknown and the row is not returned. Use IS NULL to find missing values.

Frequently Asked Questions

Is SQL BETWEEN inclusive?

Yes. BETWEEN includes both the lower and the upper value. BETWEEN 1 AND 5 returns 1, 2, 3, 4 and 5.

Can I use BETWEEN with dates?

Yes. Write the dates in the format your database expects, for example BETWEEN '2024-01-01' AND '2024-12-31'. If the column also stores a time, use >= and < with the day after the end date instead.

What is the difference between BETWEEN and IN?

BETWEEN matches a continuous range between two values. IN matches a list of specific values.

Does the order of the values in BETWEEN matter?

Yes. The lower value must come first. If the values are reversed, most databases return no rows.