Filtering: Intermediate
When you search Airbnb for a place to stay in Paris for under 150 dollars a night with a kitchen, Airbnb queries millions of listings using exactly the kind of filtering you are about to learn. It combines date availability checks, price range filters, location matching, and amenity conditions to return personalized results in under a second. A query that complex requires BETWEEN for price ranges, LIKE for location pattern matching, IN for amenity lists, and OR logic to handle alternative criteria. The intermediate filtering techniques in this lesson are what power that search.
OR and CASE expressions
Branch logic inside your queries
SQL has two core tools for branching logic. OR branches in the WHERE clause to decide which rows to keep. CASE WHEN branches in SELECT to decide what value each row should produce.
OR: Branching in WHERE
The OR operator returns rows that satisfy at least one of multiple conditions. Unlike AND, which requires all conditions to be true, OR is inclusive. A row passes the filter if any single condition evaluates to true.
Each condition is checked in sequence. If any evaluates to true, the row is included. When you have many OR conditions on the same column, the IN operator is a cleaner shorthand.
CASE WHEN in SELECT
While OR decides which rows to include, CASE WHEN decides what value to produce for each row. It evaluates conditions top to bottom and returns the value for the first match:
The CASE expression checks each WHEN condition in order. The first true condition determines the result. If none match, ELSE provides a default. Without ELSE, unmatched rows return NULL.
CASEstarts the expressionWHENconditionTHENvalue: one branch (repeat as needed)ELSEvalue: default if no conditions match (optional)ENDcloses the expression (required)
How They Compare
Both OR and CASE WHEN evaluate conditions, but they serve different purposes:
ORis used inWHEREto filter rows (keep or discard)CASEis used inSELECTto produce a new column value per rowORchanges which rows appear in resultsCASEchanges what values appear in results
Try using CASE WHEN to classify rows based on a condition.
> Complete this query to label orders as "high" when the amount is 500 or more, and "low" otherwise.
SELECT order_id, amount, amount >= 500 THEN 'high' ELSE 'low' END AS priority FROM orders
OR is fundamentally different from AND: it expands your result set rather than narrowing it, so a single true condition is enough to keep a row.
CASE WHEN is one of the most versatile tools in SQL because it lets you embed conditional logic directly inside a SELECT list without filtering any rows out.
When you have many OR conditions on the same column, replacing them with an IN list makes the query significantly easier to read and extend.
Operator precedence
Control how filter conditions evaluate
Default Evaluation Order
• Comparison operators (=, <, >, IN)
• Logical NOT
• Logical AND
• Logical OR
Without Parentheses
The animation below shows how SQL actually evaluates this WHERE clause. Notice the order of operations: comparisons first, then the AND, then the OR.
| user_id | country | status | total_spent |
|---|---|---|---|
| user_42 | US | active | 500 |
| user_89 | US | active | 750 |
| user_156 | CA | inactive | 1200 |
| user_203 | UK | inactive | 1500 |
| user_310 | US | inactive | 300 |
| user_id | country | status | total_spent |
|---|
Without parentheses, this expression evaluates as:
(country = 'US' AND status = 'active') OR (total_spent > 1000)
The AND executes before OR. As a result, it returns both active U.S. users and any users (in any country) who have spent more than 1000.
Parentheses for Control
Explicit Grouping
Now the parentheses force SQL to evaluate the OR condition first. The query returns only users in the U.S. who are either active or high spenders. This difference in parentheses changes the meaning, and the result set, completely.
Nested Parentheses
The database evaluates each group independently, then combines them using OR.
AND and OR, always use parentheses. Even if you know the precedence rules, the next person reading your query might not.> Complete this query to find US or Canadian orders over 500, using parentheses to group correctly.
SELECT order_id, country, total FROM orders WHERE ( country = 'US' country = 'CA' ) total > 500
The AND-before-OR precedence rule trips up experienced engineers regularly. Treating parentheses as mandatory whenever you mix AND and OR is the safest habit to develop.
LIKE for pattern matching
Search text with wildcard patterns
Why use LIKE?
When you only know part of a value, such as the prefix of an email, the substring of a URL, or the final digits of an ID, LIKE lets you match flexible patterns without writing multiple OR clauses.
LIKE supports two wildcards: % matches zero or more characters, and _ matches exactly one character. Combine them to target just the pieces you care about.
Common LIKE patterns:
Wildcard Patterns
The power of LIKE comes from wildcards that match variable portions of text.
Suffix Matching
You can invert the logic with NOT LIKE, or add multiple patterns using OR/AND for more explicit control.
Pattern matching with LIKE is one of the most practical filtering techniques in everyday SQL.
> Complete this query to find all products whose name starts with "Pro".
SELECT product_id, product_name FROM products WHERE product_name
LIKE is case-sensitive by default in most databases. Wrap both sides in LOWER() for case-insensitive matching.
LIMIT and OFFSET for pagination
Return results one page at a time
Large tables can return millions of rows. LIMIT keeps results manageable and queries performant.
Why limit rows?
Production tables regularly hold millions of rows, but dashboards rarely need the full data set. LIMIT lets you cap how many rows return, keeping result sets predictable and fast.
LIMIT is typically paired with ORDER BY so the "top" rows are deterministic. Otherwise you may get a different subset on each run.
Example
Here we sort by the metric we care about, then keep only the first five rows. LIMIT always goes at the end of the statement.
Navigating Large Datasets
OFFSET lets you skip rows, enabling pagination through results page by page.
Pagination Syntax
Pair LIMIT with OFFSET to skip rows and paginate through result pages:
- Always combine
LIMITwithORDER BYso the returned slice is stable. - When sampling data for debugging,
LIMITkeeps result sets readable and reduces query costs. - Use
OFFSETfor pagination, but be aware that large offsets can be slow on huge tables.
Controlling result size with LIMIT is essential for both performance and usability.
> Complete this query to get the 3 most expensive products.
SELECT product_name, price FROM products ORDER BY price LIMIT
Always pair LIMIT with ORDER BY to get deterministic results. Without ORDER BY, the rows returned by LIMIT are unpredictable.
OFFSET skips rows before starting to return results, enabling pagination through large datasets page by page.
Large OFFSET values can be slow because the database must still process all skipped rows internally.
BETWEEN for range filtering
Select rows within a value range
BETWEEN provides a clean syntax for filtering values within an inclusive range.
What BETWEEN does
BETWEEN expresses inclusive ranges. It translates to "greater than or equal to the lower bound AND less than or equal to the upper bound." It works with numbers, dates, and even text (alphabetical ranges).
Combining Multiple Ranges
BETWEEN works seamlessly with AND to filter on multiple range criteria simultaneously.
Multi-Range Filtering
This query narrows the data set to Q1 orders whose totals fall within a band. Stacking BETWEEN with AND combines date and numeric ranges cleanly.
BETWEEN is inclusive on both ends. For TIMESTAMP columns, this means BETWEEN '2024-01-01' AND '2024-03-31' includes midnight on March 31st. Use explicit >= / < when you need half-open ranges.> Complete this query to find orders placed between January 1st and March 31st, 2024.
SELECT order_id, order_date, total FROM orders WHERE order_date '2024-01-01' '2024-03-31'
BETWEEN provides the most readable syntax for inclusive range queries and communicates intent clearly to anyone reviewing the code later.
Stacking multiple BETWEEN conditions with AND is a clean pattern for filtering data across several dimensions simultaneously, such as date range and value range together.
> You are a marketing analyst at Uber building a customer segmentation query that identifies high-value riders for a re-engagement campaign. You need to surface riders who match several overlapping criteria across spend, activity date, and email domain without writing unwieldy chains of conditions.
OR and CASE expressions flag riders who match any one of several high-value tiers such as frequent or premium without requiring separate queries per tier.AND and OR conditions bind first, so parentheses are used to ensure the tier logic groups correctly.LIKE with wildcard patterns filters email addresses matching company domains like %@corp.com to identify business account riders eligible for enterprise offers.BETWEEN applies an inclusive date range to restrict the dataset to riders who took at least one trip within the past 90-day re-engagement window.OR returns rows matching any of several conditions; a row passes if any single condition is trueAND has higher precedence than OR, so SQL evaluates AND conditions first by defaultAND and OR to make your intent clearLIKE with % matches zero or more characters; _ matches exactly one characterLIMIT caps the number of returned rows; pair with ORDER BY for consistent resultsOFFSET skips rows for pagination (e.g., LIMIT 10 OFFSET 20 returns rows 21-30)BETWEEN provides inclusive range filtering and works with numbers, dates, and textFiltering: Intermediate
Boolean logic: it\
Boolean logic: it's complicated
- Category
- SQL
- Difficulty
- intermediate
- Duration
- 24 minutes
- Challenges
- 0 hands-on challenges
Topics covered: OR and CASE expressions, Operator precedence, LIKE for pattern matching, LIMIT and OFFSET for pagination, BETWEEN for range filtering
Lesson Sections
- OR and CASE expressions (concepts: sqlCaseWhen)
OR: Branching in WHERE CASE WHEN in SELECT How They Compare Which approach labels users as admin vs non-admin?
- Operator precedence (concepts: sqlOperatorPrecedence)
SQL evaluates operators in a specific order. Knowing this order prevents logical errors in complex conditions. Default Evaluation Order Parentheses () control the order in which SQL evaluates conditions. They act as explicit grouping tools that override default logical precedence. Without parentheses, SQL follows a fixed hierarchy: When a condition involves multiple operators, parentheses ensure the database interprets your intent correctly. They determine which comparisons are grouped and how c
- LIKE for pattern matching (concepts: sqlLike)
When exact matching is too restrictive, pattern matching lets you find rows based on partial values. Why use LIKE? The first pattern starts with Ann, the second ends with @company.com, and the third uses underscores for unknown digits. Wildcard Patterns Suffix Matching This filter keeps any email ending with @orbit.ai regardless of the username. The database scans the email column row by row and keeps entries whose suffix matches the wildcard pattern. Which pattern finds emails ending in .com? T
- LIMIT and OFFSET for pagination
Why limit rows? Example Navigating Large Datasets Pagination Syntax This skips the first 10 rows and returns the next 5 (rows 11-15). Which query safely gets the top 5 spenders?
- BETWEEN for range filtering (concepts: sqlBetween)
What BETWEEN does It keeps range logic concise, especially when both bounds are constants or parameters. Combining Multiple Ranges Multi-Range Filtering For date range queries, always consider whether you need inclusive or exclusive boundaries because including midnight on the last day can pull in unexpected records.