ποΈ SQL Β· Topic 3 of 20
Filtering with WHERE β SQL Questions with Answers
30 practice questions on Filtering with WHERE, each with the correct answer and a clear explanation of why it is right. Read through them as revision notes, or take this topic as an interactive quiz to test yourself.
3 easy Β· 16 medium Β· 11 hard Β· Part of SQL: Databases from basics to window functions - 20 topics.
Medium questions (16)
Q4. medium
How do you require TWO conditions to both be true?
- A WHERE age > 18 AND city = 'Delhi'
- B WHERE age > 18 && city = 'Delhi'
- C WHERE age > 18, city = 'Delhi'
- D WHERE both(age > 18, city = 'Delhi')
Answer: A β WHERE age > 18 AND city = 'Delhi'
SQL uses the words AND, OR and NOT rather than symbols. (MySQL accepts && but it is non-standard.)
Logical operators
Q6. medium
What does BETWEEN do?
WHERE marks BETWEEN 50 AND 80
- A Matches values from 50 to 80 INCLUSIVE of both ends
- B Matches 51 to 79
- C Matches only 50 and 80
- D Matches values outside the range
Answer: A β Matches values from 50 to 80 INCLUSIVE of both ends
BETWEEN is inclusive: equivalent to marks >= 50 AND marks <= 80. Remember this when working with dates, where the upper bound often surprises people.
BETWEENRanges
Q8. medium
What does IN do?
WHERE city IN ('Delhi', 'Mumbai', 'Pune')
- A Matches rows whose city equals ANY value in the list
- B Matches rows containing those letters
- C Requires all three cities
- D Is the same as BETWEEN
Answer: A β Matches rows whose city equals ANY value in the list
IN is shorthand for a chain of ORs and is far more readable. It can also take a subquery: WHERE id IN (SELECT customer_id FROM orders).
INSubqueries
Q9. medium
What does LIKE 'A%' match?
WHERE name LIKE 'A%' -- starts with A
WHERE name LIKE '%son' -- ends with son
WHERE name LIKE '%an%' -- contains an
WHERE code LIKE 'A_1' -- A, any char, 1
- A Any value STARTING with A - % matches zero or more characters
- B Only the exact text 'A%'
- C Values ending with A
- D Values containing exactly one A
Answer: A β Any value STARTING with A - % matches zero or more characters
% is the multi-character wildcard and _ matches exactly one character. So 'A%' is starts-with, '%a%' is contains, and '_a%' means second letter is a.
LIKEWildcards
Q10. medium
What does the _ wildcard match in LIKE?
- A Exactly ONE character
- B Zero or more characters
- C A literal underscore
- D A space
Answer: A β Exactly ONE character
'J_n' matches Jan and Jon but not Jain. To match a literal underscore or percent sign, use an ESCAPE clause.
LIKEWildcards
Q14. medium
What does NOT IN do when the list contains a NULL?
WHERE id NOT IN (1, 2, NULL)
- A It returns NO rows at all - a classic NULL trap
- B It ignores the NULL
- C It returns all rows
- D It throws an error
Answer: A β It returns NO rows at all - a classic NULL trap
NOT IN expands to id <> 1 AND id <> 2 AND id <> NULL, and the last comparison is always UNKNOWN, so the whole condition can never be TRUE. Use NOT EXISTS, or filter NULLs from the subquery.
- A famous SQL interview question.
NOT INNULLNOT EXISTS
Q15. medium
How do you negate a condition?
- A WHERE NOT (age > 18) - or use the opposite operator: age <= 18
- B WHERE !age > 18
- C WHERE age NOT > 18
- D WHERE opposite(age > 18)
Answer: A β WHERE NOT (age > 18) - or use the opposite operator: age <= 18
NOT inverts a condition. It also combines with other keywords: NOT IN, NOT LIKE, NOT BETWEEN, IS NOT NULL.
NOTNegation
Q16. medium
Is string comparison in WHERE case-sensitive?
- A It depends on the database's COLLATION - MySQL is usually case-insensitive, PostgreSQL is case-sensitive
- B Always case-sensitive
- C Always case-insensitive
- D Only for numbers
Answer: A β It depends on the database's COLLATION - MySQL is usually case-insensitive, PostgreSQL is case-sensitive
Because behaviour varies, portable code normalises both sides: WHERE LOWER(email) = LOWER('Ana@X.com'). Note that wrapping the column in a function can prevent index use.
CollationCase sensitivity
Q17. medium
Which query finds students with marks over 90 OR under 20?
- A WHERE marks > 90 OR marks < 20
- B WHERE marks > 90 AND marks < 20
- C WHERE marks BETWEEN 90 AND 20
- D WHERE marks NOT BETWEEN 20 AND 90
Answer: A β WHERE marks > 90 OR marks < 20
Option B can never be true (no number is both). Option D is close but INCLUSIVE at the boundaries, so it excludes exactly 20 and 90 differently from option A.
ORRanges
Q19. medium
What does this return?
SELECT * FROM orders WHERE total > 100 AND total < 100;
- A Zero rows - the conditions contradict each other
- B All rows
- C Rows equal to 100
- D An error
Answer: A β Zero rows - the conditions contradict each other
No value satisfies both. Contradictory filters usually mean AND was written where OR was intended.
LogicAND
Q20. medium
How do you filter on a boolean column?
- A WHERE is_active = TRUE (or = 1 where booleans are stored as integers)
- B WHERE is_active is on
- C WHERE is_active
- D WHERE active(is_active)
Answer: A β WHERE is_active = TRUE (or = 1 where booleans are stored as integers)
PostgreSQL has a real BOOLEAN type and even allows bare 'WHERE is_active'. MySQL stores booleans as TINYINT, so = 1 is normal.
BooleansDialects
Q22. medium
How do you find rows where a text column is empty OR missing?
- A WHERE name IS NULL OR name = ''
- B WHERE name = NULL
- C WHERE name IS EMPTY
- D WHERE LENGTH(name) = NULL
Answer: A β WHERE name IS NULL OR name = ''
An empty string and NULL are different values in SQL: '' is a known-but-blank value, NULL is unknown. Real data often contains both, so check for both.
NULLEmpty string
Q23. medium
What does WHERE id IN (SELECT customer_id FROM orders) do?
- A Keeps customers who have at least one order - a subquery supplies the list
- B Is invalid syntax
- C Returns all customers
- D Joins the tables
Answer: A β Keeps customers who have at least one order - a subquery supplies the list
IN accepts a subquery returning one column. For large data, EXISTS often performs better and handles NULLs more safely.
SubqueriesINEXISTS
Q25. medium
Which query is written correctly?
- A SELECT name FROM users WHERE age > 18 ORDER BY name;
- B SELECT name FROM users ORDER BY name WHERE age > 18;
- C SELECT name WHERE age > 18 FROM users;
- D WHERE age > 18 SELECT name FROM users;
Answer: A β SELECT name FROM users WHERE age > 18 ORDER BY name;
Clause order is fixed: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT. Writing them out of order is a syntax error.
Clause order
Q27. medium
How would you exclude several statuses?
- A WHERE status NOT IN ('cancelled', 'refunded')
- B WHERE status != ('cancelled', 'refunded')
- C WHERE NOT status = 'cancelled', 'refunded'
- D WHERE status EXCEPT ('cancelled')
Answer: A β WHERE status NOT IN ('cancelled', 'refunded')
NOT IN is the readable form. Remember it silently returns nothing if the list contains NULL, and that rows where status itself is NULL are excluded too.
NOT INNULL
Q30. medium
Before running a DELETE, what is the safest habit?
- A Run the same WHERE clause in a SELECT first to see exactly which rows will be affected
- B Run it and check afterwards
- C Use DELETE without WHERE first
- D Disable the index
Answer: A β Run the same WHERE clause in a SELECT first to see exactly which rows will be affected
Previewing with SELECT (and wrapping changes in a transaction you can roll back) prevents the classic disaster of a DELETE whose WHERE was wrong - or missing entirely.
SafetyDELETETransactions
Hard questions (11)
Q5. hard
Which has higher precedence: AND or OR?
-- probably WRONG:
WHERE city = 'Delhi' OR city = 'Mumbai' AND active = 1
-- means: Delhi OR (Mumbai AND active)
-- intended:
WHERE (city = 'Delhi' OR city = 'Mumbai') AND active = 1
- A AND - so 'a OR b AND c' means 'a OR (b AND c)'
- B OR
- C They are equal, evaluated left to right
- D It depends on the database
Answer: A β AND - so 'a OR b AND c' means 'a OR (b AND c)'
AND binds tighter, exactly like multiplication before addition. This causes real bugs - use parentheses whenever you mix them.
- A very common interview question and a frequent real-world bug.
PrecedenceParentheses
Q7. hard
Why is 'WHERE order_date BETWEEN '2026-01-01' AND '2026-01-31'' risky?
WHERE order_date >= '2026-01-01'
AND order_date < '2026-02-01'
- A If the column stores times, rows later on 31 Jan (e.g. 14:30) are EXCLUDED because the bound means midnight
- B BETWEEN does not work with dates
- C The dates need to be numbers
- D It is perfectly safe
Answer: A β If the column stores times, rows later on 31 Jan (e.g. 14:30) are EXCLUDED because the bound means midnight
A DATETIME of 2026-01-31 14:30 is greater than 2026-01-31 00:00. The safe pattern uses a half-open range: >= start AND < next_month_start.
DatesBETWEENGotchas
Q11. hard
Why can 'WHERE name LIKE '%son'' be slow on a large table?
- A A leading wildcard prevents the database using an index, forcing a full scan
- B LIKE is always slow
- C It uses too much memory
- D It is not slow
Answer: A β A leading wildcard prevents the database using an index, forcing a full scan
Indexes work like a dictionary - sorted by the start of the value. 'A%' can seek directly; '%son' must check every row. For contains-searches at scale, use full-text search.
IndexesPerformance
Q12. hard
How do you correctly test for a NULL value?
WHERE email IS NULL
WHERE email IS NOT NULL
- A WHERE email IS NULL
- B WHERE email = NULL
- C WHERE email == NULL
- D WHERE email = 'NULL'
Answer: A β WHERE email IS NULL
NULL means 'unknown', and comparing anything to unknown yields UNKNOWN - never TRUE. So = NULL silently matches nothing. Always use IS NULL / IS NOT NULL.
- One of the most-tested SQL concepts.
NULLThree-valued logic
Q13. hard
What does 'WHERE status <> 'shipped'' return for rows where status is NULL?
- A It EXCLUDES them - NULL <> 'shipped' is UNKNOWN, not TRUE
- B It includes them
- C It throws an error
- D It includes them only in MySQL
Answer: A β It EXCLUDES them - NULL <> 'shipped' is UNKNOWN, not TRUE
A frequent bug: 'everything not shipped' silently drops NULL rows. Write: WHERE status <> 'shipped' OR status IS NULL.
NULLGotchas
Q18. hard
Why avoid wrapping a column in a function in WHERE?
WHERE YEAR(order_date) = 2026
- A It makes the condition non-sargable - the index on order_date cannot be used
- B YEAR() does not exist
- C It returns wrong results
- D There is no problem
Answer: A β It makes the condition non-sargable - the index on order_date cannot be used
The database must compute YEAR() for every row before comparing. Rewrite as a range so the index works: order_date >= '2026-01-01' AND order_date < '2027-01-01'.
SargableIndexesPerformance
Q21. hard
What is the result of comparing NULL = NULL?
- A UNKNOWN - not TRUE, because two unknown values cannot be proven equal
- B TRUE
- C FALSE
- D An error
Answer: A β UNKNOWN - not TRUE, because two unknown values cannot be proven equal
SQL uses three-valued logic: TRUE, FALSE and UNKNOWN. WHERE keeps only TRUE rows, so NULL comparisons filter everything out. (The IS NOT DISTINCT FROM operator treats NULLs as equal where supported.)
NULLThree-valued logic
Q24. hard
What is the difference between WHERE and HAVING?
SELECT dept, COUNT(*) AS n
FROM employees
WHERE active = 1 -- rows first
GROUP BY dept
HAVING COUNT(*) > 5; -- then groups
- A WHERE filters individual ROWS before grouping; HAVING filters GROUPS after aggregation
- B They are interchangeable
- C HAVING is faster
- D WHERE only works with numbers
Answer: A β WHERE filters individual ROWS before grouping; HAVING filters GROUPS after aggregation
Aggregates like COUNT(*) cannot appear in WHERE because grouping has not happened yet. Filter raw rows in WHERE (more efficient) and group results in HAVING.
HAVINGGROUP BY
Q26. hard
What does this match?
WHERE phone LIKE '9%' AND LENGTH(phone) = 10
- A Ten-character phone numbers starting with 9
- B Any number containing 9
- C Numbers ending in 9
- D An error
Answer: A β Ten-character phone numbers starting with 9
Combining pattern matching with a length check is a common validation query for finding malformed data. (Some databases call the function LEN instead of LENGTH.)
LIKEData validation
Q28. hard
What does 'WHERE 1=1' accomplish in generated SQL?
WHERE 1=1
AND city = 'Delhi'
AND active = 1
- A It is an always-true placeholder, so every real condition can be appended with AND
- B It filters one row
- C It speeds up the query
- D It is a syntax error
Answer: A β It is an always-true placeholder, so every real condition can be appended with AND
When code builds queries dynamically, starting with 1=1 avoids awkward logic about whether to write WHERE or AND. Optimisers ignore the constant.
Dynamic SQLTricks
Q29. hard
Why should application code use parameterised queries instead of building WHERE strings?
-- safe (placeholder):
SELECT * FROM users WHERE email = ?;
- A To prevent SQL injection - user input is sent separately from the query text
- B To make queries shorter
- C Because concatenation is a syntax error
- D It makes no difference
Answer: A β To prevent SQL injection - user input is sent separately from the query text
Concatenating input allows an attacker to inject SQL (e.g. ' OR 1=1 --). Parameters keep data and code separate, so input can never change the query's structure.
SQL injectionSecurity