Wicked Smart Data
LearnArticlesAbout
Sign InSign Up
LearnArticlesAboutContact
Sign InSign Up
Wicked Smart Data

The go-to platform for professionals who want to master data, automation, and AI — from Excel fundamentals to cutting-edge machine learning.

Platform

  • Learning Paths
  • Articles
  • About
  • Contact

Connect

  • Contact Us
  • RSS Feed

© 2026 Wicked Smart Data. All rights reserved.

Privacy PolicyTerms of Service
All Articles
Filtering and Sorting Data in SQL: Master WHERE, AND, OR, IN, BETWEEN, and ORDER BY

Filtering and Sorting Data in SQL: Master WHERE, AND, OR, IN, BETWEEN, and ORDER BY

SQL🌱 Foundation13 min readMay 3, 2026Updated May 3, 2026
Table of Contents
  • Prerequisites
  • Understanding the WHERE Clause: Your Data Filter
  • Combining Conditions with AND: All Criteria Must Match
  • Using OR for Alternative Conditions: Any Match Will Do
  • The Power of Parentheses: Controlling Logic Order
  • Efficient List Filtering with IN
  • Range Filtering with BETWEEN
  • Sorting Your Results with ORDER BY
  • Multi-Level Sorting: When One Column Isn't Enough
  • Combining Everything: Complex Real-World Queries
  • Hands-On Exercise
  • Common Mistakes & Troubleshooting

You're staring at a spreadsheet with 50,000 customer records, and your manager just asked you to find all customers from California or Texas who made purchases between $100 and $500 last month, sorted by purchase amount. In Excel, this would take forever and be prone to errors. In SQL, it's a single, elegant query that runs in milliseconds.

This is the power of SQL's filtering and sorting capabilities. While basic SELECT statements let you retrieve data, the real magic happens when you can precisely specify which rows you want and how you want them organized. Think of it like having a incredibly smart assistant who can instantly sift through millions of records and present exactly what you need, organized exactly how you want it.

What you'll learn:

  • How to filter data using WHERE clauses to find specific records
  • How to combine multiple conditions with AND, OR, and parentheses for complex logic
  • How to use IN and BETWEEN for efficient range and list filtering
  • How to sort results with ORDER BY for meaningful data presentation
  • How to avoid common filtering mistakes that lead to unexpected results

Prerequisites

You should be comfortable with basic SELECT statements and understand how to retrieve all columns or specific columns from a table. If you haven't worked through basic SQL syntax yet, start there first.

Understanding the WHERE Clause: Your Data Filter

The WHERE clause is SQL's primary filtering mechanism. It works like a bouncer at an exclusive club – it examines each row in your table and only lets through the ones that meet your criteria.

Let's start with a realistic example. Imagine you're working with an e-commerce database containing a customers table:

SELECT customer_id, first_name, last_name, state, signup_date, total_spent
FROM customers
WHERE state = 'California';

This query examines every row in the customers table and returns only those where the state column exactly matches 'California'. Notice a few important things:

  • The WHERE clause comes after the FROM clause
  • We use a single equals sign (=) for comparison, not the double equals (==) you might know from programming languages
  • Text values are enclosed in single quotes

The WHERE clause doesn't change your table – it's like putting a filter on a camera lens. The original data remains unchanged, but you only see the rows that meet your criteria.

Let's see what different comparison operators do:

-- Find customers who spent more than $1000
SELECT first_name, last_name, total_spent
FROM customers
WHERE total_spent > 1000;

-- Find customers who joined before 2023
SELECT first_name, last_name, signup_date
FROM customers
WHERE signup_date < '2023-01-01';

-- Find customers who are NOT from California
SELECT first_name, last_name, state
FROM customers
WHERE state != 'California';

Tip: In SQL, you can use either != or <> for "not equal." Both work the same way, though <> is more standard in formal SQL.

Combining Conditions with AND: All Criteria Must Match

Real business questions rarely have just one condition. You might need customers from California AND who spent more than $500 AND who joined in the last year. The AND operator requires ALL conditions to be true for a row to be included.

SELECT first_name, last_name, state, total_spent, signup_date
FROM customers
WHERE state = 'California' 
  AND total_spent > 500 
  AND signup_date >= '2023-01-01';

Think of AND like a series of gates. A row must pass through ALL gates to make it into your results. If any condition fails, the entire row is rejected.

Here's a more complex business scenario: find high-value customers in key markets who are still active:

SELECT customer_id, first_name, last_name, state, total_spent, last_purchase_date
FROM customers
WHERE (state = 'California' OR state = 'New York' OR state = 'Texas')
  AND total_spent > 1000
  AND last_purchase_date > '2024-01-01';

Notice how we use parentheses to group the state conditions. This ensures the OR logic applies only to the states, while the AND conditions apply to the entire group.

Using OR for Alternative Conditions: Any Match Will Do

While AND requires all conditions to be true, OR is satisfied if ANY of the conditions are true. It's like having multiple doors – you only need to fit through one of them.

-- Find customers from either coast
SELECT first_name, last_name, state
FROM customers
WHERE state = 'California' OR state = 'New York';

-- Find customers who are either high spenders OR recent joiners
SELECT first_name, last_name, total_spent, signup_date
FROM customers
WHERE total_spent > 2000 OR signup_date > '2024-01-01';

The key insight with OR is that a single row might satisfy multiple conditions, but it will only appear once in your results. If a customer is from California AND spent more than $2000, they'll still appear only once in the second query above.

The Power of Parentheses: Controlling Logic Order

Just like in math, parentheses control the order of operations in SQL. Without them, you can get unexpected results because AND has higher precedence than OR.

Consider this problematic query:

-- PROBLEMATIC: This doesn't do what you probably think it does
SELECT first_name, last_name, state, total_spent
FROM customers
WHERE state = 'California' OR state = 'Texas' AND total_spent > 1000;

Due to operator precedence, SQL reads this as:

  • state = 'California' OR (state = 'Texas' AND total_spent > 1000)

This means you'll get ALL California customers (regardless of spending) plus Texas customers who spent more than $1000. Probably not what you wanted!

Here's the corrected version:

-- CORRECT: High spenders from California OR Texas
SELECT first_name, last_name, state, total_spent
FROM customers
WHERE (state = 'California' OR state = 'Texas') AND total_spent > 1000;

Now you get customers from either California or Texas, but only those who spent more than $1000.

Warning: When mixing AND and OR, always use parentheses to make your intentions crystal clear. It prevents bugs and makes your code readable.

Efficient List Filtering with IN

When you need to check if a value matches any item in a list, the IN operator is cleaner and more efficient than multiple OR conditions.

Instead of this verbose approach:

SELECT customer_id, first_name, last_name, state
FROM customers
WHERE state = 'California' 
   OR state = 'Texas' 
   OR state = 'Florida' 
   OR state = 'New York';

You can write this elegant alternative:

SELECT customer_id, first_name, last_name, state
FROM customers
WHERE state IN ('California', 'Texas', 'Florida', 'New York');

The IN operator works with numbers too:

-- Find orders from specific customer IDs
SELECT order_id, customer_id, order_total, order_date
FROM orders
WHERE customer_id IN (1001, 1057, 1089, 1234, 1456);

You can also use NOT IN to exclude values:

-- Find customers NOT in these states
SELECT customer_id, first_name, last_name, state
FROM customers
WHERE state NOT IN ('Alaska', 'Hawaii');

Tip: IN is not just cleaner to read – it's also more efficient for the database engine to process than multiple OR conditions.

Range Filtering with BETWEEN

When you need to find values within a range, BETWEEN provides a clean, readable solution. It's inclusive on both ends, meaning it includes the boundary values you specify.

-- Find customers who spent between $500 and $2000 (inclusive)
SELECT customer_id, first_name, last_name, total_spent
FROM customers
WHERE total_spent BETWEEN 500 AND 2000;

This is equivalent to:

SELECT customer_id, first_name, last_name, total_spent
FROM customers
WHERE total_spent >= 500 AND total_spent <= 2000;

BETWEEN works beautifully with dates:

-- Find customers who joined in 2023
SELECT customer_id, first_name, last_name, signup_date
FROM customers
WHERE signup_date BETWEEN '2023-01-01' AND '2023-12-31';

-- Find orders from the last quarter
SELECT order_id, customer_id, order_total, order_date
FROM orders
WHERE order_date BETWEEN '2024-10-01' AND '2024-12-31';

You can also use NOT BETWEEN to exclude ranges:

-- Find customers who spent either very little (under $100) or a lot (over $5000)
SELECT customer_id, first_name, last_name, total_spent
FROM customers
WHERE total_spent NOT BETWEEN 100 AND 5000;

Sorting Your Results with ORDER BY

Finding the right data is only half the battle – presenting it in a meaningful order is equally important. The ORDER BY clause sorts your results, and it always comes at the very end of your query.

-- Sort customers by total spending, highest first
SELECT customer_id, first_name, last_name, total_spent
FROM customers
WHERE state = 'California'
ORDER BY total_spent DESC;

The DESC keyword means descending order (highest to lowest). If you want ascending order (lowest to highest), you can either use ASC or omit it entirely, since ascending is the default:

-- These two queries produce identical results
SELECT customer_id, first_name, last_name, signup_date
FROM customers
ORDER BY signup_date ASC;

SELECT customer_id, first_name, last_name, signup_date
FROM customers
ORDER BY signup_date;

Multi-Level Sorting: When One Column Isn't Enough

You can sort by multiple columns to handle cases where the first column has duplicate values:

-- Sort by state first, then by total spending within each state
SELECT customer_id, first_name, last_name, state, total_spent
FROM customers
ORDER BY state, total_spent DESC;

This query first groups all customers by state (alphabetically), then within each state, sorts by spending from highest to lowest.

You can mix ascending and descending sorts:

-- Sort by state (A-Z), then by spending (highest to lowest), then by name (A-Z)
SELECT customer_id, first_name, last_name, state, total_spent
FROM customers
ORDER BY state ASC, total_spent DESC, last_name ASC;

Combining Everything: Complex Real-World Queries

Now let's combine all these concepts into queries you might actually write in your job:

-- Find medium-to-high value customers from key markets who joined recently
SELECT customer_id, first_name, last_name, state, total_spent, signup_date
FROM customers
WHERE state IN ('California', 'Texas', 'New York', 'Florida')
  AND total_spent BETWEEN 1000 AND 10000
  AND signup_date >= '2023-01-01'
ORDER BY total_spent DESC, signup_date DESC;

This query tells a story: "Show me customers from our top markets who are valuable but not whales, who joined in the last couple years, prioritizing the biggest spenders and most recent joiners."

Here's another realistic scenario:

-- Find recent orders that were either large or from VIP customers
SELECT o.order_id, o.customer_id, o.order_total, o.order_date, c.first_name, c.last_name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.order_date >= '2024-01-01'
  AND (o.order_total > 500 OR c.customer_type = 'VIP')
ORDER BY o.order_date DESC, o.order_total DESC;

Note: This query uses a JOIN, which we'll cover in detail in a future lesson. For now, just focus on the WHERE and ORDER BY logic.

Hands-On Exercise

Let's practice with a realistic scenario. You're working for a subscription service with a subscribers table containing:

  • subscriber_id
  • first_name, last_name
  • email
  • subscription_plan ('basic', 'premium', 'enterprise')
  • monthly_fee
  • signup_date
  • status ('active', 'cancelled', 'suspended')

Write queries to answer these business questions:

  1. Customer Service Priority List: Find all active subscribers who pay $50 or more monthly, sorted by monthly fee (highest first), then by signup date (oldest first).

  2. Retention Analysis: Find subscribers who signed up in 2023 and are either cancelled or suspended, from either premium or enterprise plans.

  3. Upsell Opportunities: Find active basic plan subscribers who signed up more than 6 months ago, sorted by signup date.

Here are the solutions:

-- 1. Customer Service Priority List
SELECT subscriber_id, first_name, last_name, subscription_plan, monthly_fee, signup_date
FROM subscribers
WHERE status = 'active' 
  AND monthly_fee >= 50
ORDER BY monthly_fee DESC, signup_date ASC;

-- 2. Retention Analysis
SELECT subscriber_id, first_name, last_name, subscription_plan, status, signup_date
FROM subscribers
WHERE signup_date BETWEEN '2023-01-01' AND '2023-12-31'
  AND status IN ('cancelled', 'suspended')
  AND subscription_plan IN ('premium', 'enterprise')
ORDER BY signup_date DESC;

-- 3. Upsell Opportunities
SELECT subscriber_id, first_name, last_name, email, signup_date
FROM subscribers
WHERE status = 'active'
  AND subscription_plan = 'basic'
  AND signup_date < '2024-06-01'  -- Assuming today is around December 2024
ORDER BY signup_date ASC;

Common Mistakes & Troubleshooting

Mistake #1: Forgetting quotes around text values

-- WRONG: This will cause an error
SELECT * FROM customers WHERE state = California;

-- RIGHT: Always quote text values
SELECT * FROM customers WHERE state = 'California';

Mistake #2: Mixing up AND and OR logic

-- WRONG: This gets all CA customers plus TX customers with >$1000 spending
SELECT * FROM customers 
WHERE state = 'California' OR state = 'Texas' AND total_spent > 1000;

-- RIGHT: Use parentheses to group OR conditions
SELECT * FROM customers 
WHERE (state = 'California' OR state = 'Texas') AND total_spent > 1000;

Mistake #3: Case sensitivity issues Different databases handle case sensitivity differently. In some systems, 'California' and 'california' are different values.

-- Better approach: Use UPPER() or LOWER() for consistent matching
SELECT * FROM customers 
WHERE UPPER(state) = 'CALIFORNIA';

Mistake #4: NULL value surprises NULL values don't behave like you might expect:

-- This WON'T find rows where total_spent is NULL
SELECT * FROM customers WHERE total_spent != 0;

-- To include or exclude NULL values, be explicit:
SELECT * FROM customers 
WHERE total_spent > 0 OR total_spent IS NULL;

Mistake #5: Date format confusion Always use the standard 'YYYY-MM-DD' format for dates:

-- RIGHT: Standard format works everywhere
WHERE signup_date > '2023-12-25'

-- WRONG: This might not work as expected
WHERE signup_date > '12/25/2023'

Summary & Next Steps

You now have the core skills for filtering and sorting data in SQL. You can:

  • Use WHERE clauses to filter rows based on specific criteria
  • Combine multiple conditions with AND, OR, and parentheses for complex logic
  • Use IN for efficient list matching and BETWEEN for range filtering
  • Sort results with ORDER BY for meaningful data presentation
  • Avoid common pitfalls that trip up many SQL beginners

These skills form the foundation for virtually every SQL query you'll write. Even complex analytical queries ultimately come down to filtering the right data and presenting it in the right order.

Your next steps should be:

  1. Practice with real data: Find a sample database (like the Northwind sample database) and practice writing increasingly complex queries
  2. Learn about JOINs: Most real-world queries need data from multiple tables, which requires understanding JOIN operations
  3. Explore aggregate functions: Learn how to use COUNT, SUM, AVG, and GROUP BY to summarize data
  4. Study NULL handling: Understanding how SQL handles missing data is crucial for accurate results

The filtering and sorting patterns you've learned here will appear in every advanced SQL concept you encounter. Master these fundamentals, and everything else becomes much easier to understand.

Learning Path: SQL Fundamentals

Previous

Advanced SQL Filtering and Sorting: Master WHERE, Logical Operators, and ORDER BY

Next

Filtering and Sorting Data: WHERE, AND, OR, IN, BETWEEN, ORDER BY

Related Articles

SQL🔥 Expert

Advanced JOIN Patterns: Self Joins, Anti Joins, and Semi Joins

20 min
SQL⚡ Practitioner

SQL Transactions, Isolation Levels, and Locking: A Complete Guide to Concurrent Database Programming

17 min
SQL🌱 Foundation

Stored Procedures and User-Defined Functions: Building Reusable SQL Logic

14 min

On this page

  • Prerequisites
  • Understanding the WHERE Clause: Your Data Filter
  • Combining Conditions with AND: All Criteria Must Match
  • Using OR for Alternative Conditions: Any Match Will Do
  • The Power of Parentheses: Controlling Logic Order
  • Efficient List Filtering with IN
  • Range Filtering with BETWEEN
  • Sorting Your Results with ORDER BY
  • Multi-Level Sorting: When One Column Isn't Enough
  • Combining Everything: Complex Real-World Queries
  • Summary & Next Steps
  • Hands-On Exercise
  • Common Mistakes & Troubleshooting
  • Summary & Next Steps