Skip to main content
Filtering with AND, OR, IN, BETWEEN

SQL Crash Course

Filtering with AND, OR, IN, BETWEEN

Reading8 min read

Filtering with AND, OR, IN, BETWEEN

A single WHERE condition rarely captures a real test scenario. Combining conditions with AND, OR, IN, and BETWEEN is how you express "give me exactly this slice of data" — and how you verify the application is filtering correctly too.

AND vs OR

-- AND: every condition must be true
SELECT * FROM users WHERE country = 'US' AND is_active = 1;

-- OR: at least one condition must be true
SELECT * FROM orders WHERE status = 'pending' OR status = 'processing';

Operator Precedence — Use Parentheses

AND binds tighter than OR. Without parentheses, a mixed condition can silently filter the wrong rows:

-- Looks like "US orders that are pending or processing"...
SELECT * FROM orders
WHERE country = 'US' AND status = 'pending' OR status = 'processing';

-- ...but it actually returns ALL processing orders, regardless of country,
-- because AND is evaluated before OR. Fix it with parentheses:
SELECT * FROM orders
WHERE country = 'US' AND (status = 'pending' OR status = 'processing');

This is a real bug pattern to test for: any query (or ORM-generated query) mixing AND/OR without parentheses is a candidate for a data-filtering bug.

IN — Match Against a List

IN replaces a long chain of OR comparisons on the same column:

-- Equivalent, but IN is clearer and usually faster
SELECT * FROM orders WHERE status = 'pending' OR status = 'processing' OR status = 'on_hold';
SELECT * FROM orders WHERE status IN ('pending', 'processing', 'on_hold');

-- NOT IN excludes a list
SELECT * FROM users WHERE country NOT IN ('US', 'CA');

BETWEEN — Inclusive Ranges

-- Inclusive on both ends: price BETWEEN 10 AND 100 includes 10 and 100
SELECT * FROM products WHERE price BETWEEN 10 AND 100;

-- Dates work the same way — watch for time-of-day truncation
SELECT * FROM orders WHERE created_at BETWEEN '2024-06-01' AND '2024-06-30';
-- Careful: '2024-06-30' means midnight — orders placed later that day are excluded.
-- Safer:
SELECT * FROM orders WHERE created_at >= '2024-06-01' AND created_at < '2024-07-01';

An app feature filters orders by status and a date range at the same time:

SELECT id, status, total, created_at
FROM   orders
WHERE  status IN ('completed', 'refunded')
  AND  created_at >= '2024-06-01' AND created_at < '2024-07-01'
ORDER BY created_at DESC;

Run this directly against the database and compare the row count and IDs against what the UI shows. A mismatch usually means the application is missing a condition, using the wrong boundary (<= vs <), or combining AND/OR incorrectly.

Q
Knowledge Check

Without parentheses, what does `WHERE country = 'US' AND status = 'pending' OR status = 'processing'` actually match?

Next Lesson

Sorting & Limiting Results

SELECT, FROM, WHERE Basics