DevNotes
Support
SQL & MySQL · Chapter 03

Filtering Data

The heart of SQL — WHERE, comparison and logical operators, operator precedence, BETWEEN, IN, LIKE, REGEXP, NULL handling, LIMIT/OFFSET and logical execution order.

◷ 7 min read§ 17 sections? 8 interview questions{ } 23 code examples

#Introduction

Spring Boot APIs, JPA queries, Hibernate, reports, dashboards, admin portals — everything revolves around filtering data.

#Sample Table

We'll use this employees table throughout the chapter:

idnamedepartmentsalarycitymanager_id
1RahulIT70000Bangalore10
2AmitHR50000DelhiNULL
3NehaIT90000Mumbai10
4RajFinance60000Bangalore20
5AnkitIT75000Chennai10

#WHERE Clause

Without WHERE, SELECT * FROM employees; returns all employees. With it:

SQL
SELECT *
FROM employees
WHERE department = 'IT';
Output
Rahul
Neha
Ankit

Think Like Java

SQL
WHERE salary > 50000
Java
if (employee.getSalary() > 50000) {
    // include employee
}

A WHERE clause is essentially a filter condition.

#Comparison Operators

OperatorMeaning
=Equal
!= or <>Not equal
>Greater than
>=Greater than or equal
<Less than
<=Less than or equal
SQL
SELECT *
FROM employees
WHERE salary > 70000;
Output
Neha
Ankit

#Logical Operators

AND — All Conditions Must Be True

SQL
SELECT *
FROM employees
WHERE department = 'IT'
  AND salary > 70000;
Output
Neha
Ankit

Java equivalent: if (department.equals("IT") && salary > 70000).

OR — Either Condition Can Be True

SQL
SELECT *
FROM employees
WHERE city = 'Delhi'
   OR city = 'Mumbai';
Output
Amit
Neha

Java equivalent: if (city.equals("Delhi") || city.equals("Mumbai")).

NOT — Reverse the Condition

SQL
SELECT *
FROM employees
WHERE NOT department = 'HR';

Everyone except HR employees.

Combining AND and OR

SQL
SELECT *
FROM employees
WHERE department = 'IT'
  AND city = 'Bangalore';      -- Rahul

SELECT *
FROM employees
WHERE department = 'IT'
   OR salary > 80000;          -- Rahul, Neha, Ankit

Parentheses Matter

SQL
-- ❌ Ambiguous
SELECT *
FROM employees
WHERE department = 'IT'
   OR city = 'Delhi'
  AND salary > 70000;

SQL evaluates AND before OR, so this means IT OR (Delhi AND salary > 70000).

SQL
-- ✅ Correct
SELECT *
FROM employees
WHERE (department = 'IT' OR city = 'Delhi')
  AND salary > 70000;

#BETWEEN

Instead of salary >= 50000 AND salary <= 70000:

SQL
SELECT *
FROM employees
WHERE salary BETWEEN 50000 AND 70000;

Much cleaner — and inclusive on both ends.

Dates

SQL
SELECT *
FROM orders
WHERE order_date BETWEEN '2026-01-01' AND '2026-01-31';

Very common in reporting.

#IN and NOT IN

Instead of city = 'Delhi' OR city = 'Mumbai' OR city = 'Bangalore':

SQL
SELECT *
FROM employees
WHERE city IN ('Delhi', 'Mumbai', 'Bangalore');

SELECT *
FROM employees
WHERE city NOT IN ('Delhi', 'Mumbai');

Cleaner and easier to maintain.

#LIKE

Pattern matching with wildcards:

SymbolMeaning
%Zero or more characters
_Exactly one character
SQL
SELECT *
FROM employees
WHERE name LIKE 'R%';    -- starts with R: Rahul, Raj
PatternMeaning
LIKE 'R%'Starts with R
LIKE '%a'Ends with a
LIKE '%ah%'Contains "ah"
LIKE '_a%'Second character is "a" (Rahul, Raj, Ram)
LIKE '_a_'Exactly three characters, "a" in the middle (Raj, Ram — not Rahul)

#REGEXP

Much more powerful than LIKE:

PatternMeaning
WHERE name REGEXP '^R'Starts with R
WHERE name REGEXP 'a Ends with a
REGEXP '[0-9]'Contains digits
REGEXP '[A-Z]{2}'Two letters in a row (case-insensitive by default)

Mostly used for validations and advanced searches. Use a binary/case-sensitive comparison (e.g. REGEXP BINARY or REGEXP_LIKE(col, pattern, 'c')) if case matters.

#NULL Handling

Suppose manager_id is 10, 20 or NULL. This is wrong:

SQL
WHERE manager_id = NULL      -- returns nothing

Correct:

SQL
WHERE manager_id IS NULL;
WHERE manager_id IS NOT NULL;

Why? NULL means unknown, not a value. Any comparison with NULL evaluates to UNKNOWN, not TRUE.

#LIMIT and OFFSET

SQL
-- First five employees
SELECT *
FROM employees
LIMIT 5;

-- Pagination: skip the first 20 rows, return the next 10
SELECT *
FROM employees
LIMIT 10 OFFSET 20;

In Spring Boot, PageRequest.of(2, 10) (page index 2, size 10) produces SQL similar to LIMIT 10 OFFSET 20.

#Logical Execution Order

Many developers think SQL executes top to bottom. Actually:

SQL
SELECT name
FROM employees
WHERE salary > 70000
ORDER BY salary;
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
LIMIT

This explains why aliases from the SELECT list usually can't be referenced in WHERE — WHERE is evaluated before SELECT.

#Real Spring Boot Example

Java
List<Employee> findByDepartmentAndSalaryGreaterThan(String department, Double salary);

Generated SQL:

SQL
SELECT *
FROM employees
WHERE department = ?
  AND salary > ?;

JPQL:

Java
@Query("""
        SELECT e
        FROM Employee e
        WHERE e.salary > :salary
        """)

becomes SQL similar to SELECT * FROM employees WHERE salary > ?. Understanding SQL makes debugging JPA much easier.

#Performance Tips

✅ WHERE salary = 50000 uses an index efficiently (if one exists).

❌ Avoid wrapping indexed columns in functions:

SQL
WHERE YEAR(joining_date) = 2026

This often prevents index usage. Prefer:

SQL
WHERE joining_date >= '2026-01-01'
  AND joining_date <  '2027-01-01'

(More on this in the indexing chapter.) And avoid SELECT * — fetch only the needed columns.

#Interview Questions

Q1Difference between WHERE and HAVING?

WHERE filters rows before grouping; HAVING filters groups after GROUP BY and can use aggregates like COUNT(*).

Q2IN vs EXISTS?

IN compares a value against a list or subquery result; EXISTS checks whether a correlated subquery returns any row. Covered in detail in the subqueries chapters.

Q3Difference between LIKE and REGEXP?

LIKE supports only the % and _ wildcards; REGEXP supports full regular expressions (anchors, character classes, repetition).

Q4Why can't we use = with NULL?

Because NULL is unknown — x = NULL evaluates to UNKNOWN, never TRUE. Use IS NULL / IS NOT NULL.

Q5BETWEEN vs >= and <=?

They're equivalent: BETWEEN a AND b is inclusive on both ends. For datetimes, an explicit half-open range (>= start AND < next) is safer.

Q6Difference between % and _ in LIKE?

% matches zero or more characters; _ matches exactly one.

Q7Why are parentheses important with AND and OR?

Because AND binds more tightly than OR; without parentheses, the condition may be grouped differently from what you intended.

Q8Why is WHERE YEAR(date_column) = 2026 often slower than a date range filter?

Applying a function to the column prevents MySQL from using an index on it, forcing it to evaluate every row; a range on the raw column can use the index.

#Hands-On Assignment

Using the employees table, write queries to:

  1. Find employees in the IT department.
  2. Find employees with salary greater than 70,000.
  3. Find employees in Bangalore with salary above 60,000.
  4. Find employees whose names start with "R".
  5. Find employees whose names contain "ah".
  6. Find employees without a manager.
  7. Find employees from Bangalore, Chennai or Delhi.
  8. Find employees whose salary is between 60,000 and 80,000.
  9. Display the first three employees.
  10. Display the next three employees after skipping the first three.

Challenge Problems

  1. Find employees not in the IT department.
  2. Find names ending with t.
  3. Find names having exactly 5 characters.
  4. Find employees with a NULL manager and salary greater than 50,000.
  5. Find employees who are either in Finance or have a salary above 80,000.
  6. Write one query using AND, OR and NOT together with parentheses.

#Cheat Sheet

ClausePurpose
WHEREFilter rows
=Equal
<> / !=Not equal
ANDAll conditions must be true
ORAt least one condition must be true
NOTNegate a condition
BETWEENRange filtering (inclusive)
INMatch against a list of values
LIKESimple pattern matching
REGEXPAdvanced pattern matching
IS NULLFind NULL values
IS NOT NULLFind non-NULL values
LIMITRestrict the number of rows
OFFSETSkip rows before returning results