LIKE, IN, BETWEEN: Advanced Filtering Patterns in SQL Server

LIKE, IN, BETWEEN: Advanced Filtering Patterns in SQL Server

Basic equality filters only get you so far. Here’s the rest of the filtering toolkit — wildcard patterns, membership tests, ranges, and combining them all with AND/OR/NOT correctly — plus a NULL-comparison bug that costs beginners hours of confused debugging because it never throws an error.

The Filtering Toolkit(three ways into the same WHERE)LIKE ‘%pat%’wildcard pattern matchIN (a, b, c)shorthand for many ORsBETWEEN x AND yinclusive on both endsWHEREAND binds tighter than OR — always parenthesize when you mix them.x = NULL is alwaysfalse — zero rows, noerror. Use IS NULL.

Comparison and Logical Operators

SELECT name FROM dbo.Restaurant WHERE rating >= 4.5;
SELECT name FROM dbo.Restaurant WHERE city = 'Austin' AND rating > 4.0;
SELECT name FROM dbo.Restaurant WHERE cuisine = 'Indian' OR cuisine = 'Japanese';
SELECT name FROM dbo.Restaurant WHERE NOT (city = 'Dallas');

Operator Precedence: A Real Beginner Trap

-- Looks like "Austin restaurants, plus anything highly rated" — but AND binds tighter than OR:
SELECT name FROM dbo.Restaurant
WHERE city = 'Austin' OR cuisine = 'Italian' AND rating > 4.5;
-- Actually means: city = 'Austin' OR (cuisine = 'Italian' AND rating > 4.5)

-- Use explicit parentheses to say what you actually mean:
SELECT name FROM dbo.Restaurant
WHERE (city = 'Austin' OR cuisine = 'Italian') AND rating > 4.5;
Common mistake: Mixing AND and OR without parentheses. SQL follows standard operator precedence (AND binds tighter than OR, same as multiplication binds tighter than addition in arithmetic) — when in doubt, add parentheses. They cost nothing and remove all ambiguity, for you and for anyone reading your query later.

IN: A Cleaner Way to Write Multiple ORs

SELECT name FROM dbo.Restaurant
WHERE cuisine IN ('Indian', 'Japanese', 'Italian');

-- NOT IN excludes a list — but see the NULL warning below before relying on this
SELECT name FROM dbo.Restaurant
WHERE cuisine NOT IN ('Mexican');

BETWEEN: Inclusive on Both Ends

SELECT name, rating FROM dbo.Restaurant
WHERE rating BETWEEN 4.0 AND 4.5;
-- Equivalent to: rating >= 4.0 AND rating <= 4.5 — both endpoints are included

LIKE: Pattern Matching

Wildcard Matches
% Any sequence of characters (zero or more)
_ Exactly one character
[abc] Any single character in the set
[^abc] Any single character NOT in the set
SELECT name FROM dbo.Restaurant WHERE name LIKE 'T%';        -- starts with T
SELECT name FROM dbo.Restaurant WHERE name LIKE '%Grill%';    -- contains "Grill" anywhere
SELECT name FROM dbo.Restaurant WHERE name LIKE '_a%';        -- 2nd letter is 'a'
SELECT name FROM dbo.Restaurant WHERE name LIKE '[ST]%';      -- starts with S or T
Performance preview: A pattern starting with % (like '%Grill%' or '%Grill') can't use a standard index efficiently — SQL Server has to scan every row, because it can't know in advance where a match might start. A pattern anchored at the start ('Grill%') can. You'll see exactly why once you reach indexing in the advanced course — for now, just know that "starts with" is cheap and "contains" is comparatively expensive at scale.

The NULL Trap

WHERE price_range = NULL  →  always returns ZERO rows, no error WHERE price_range IS NULL  →  correct

NULL means "unknown," and SQL uses three-valued logic — unknown = unknown evaluates to unknown, not true. WHERE column = NULL silently returns zero rows every single time, with no error to tip you off. Always use IS NULL / IS NOT NULL instead.

NULL's Sequel: The NOT IN Trap

-- If ANY value in the list (or subquery result) is NULL, the ENTIRE NOT IN silently
-- matches zero rows — not an error, just wrong results:
SELECT name FROM dbo.Restaurant
WHERE cuisine NOT IN (SELECT cuisine FROM dbo.Restaurant WHERE cuisine IS NULL OR city = 'Dallas');
-- If that subquery returns even one NULL alongside real values, this returns nothing at all.

-- Safer: explicitly exclude NULLs from the list first, or use NOT EXISTS instead (Chapter 5)
SELECT name FROM dbo.Restaurant r
WHERE NOT EXISTS (
    SELECT 1 FROM dbo.Restaurant r2 WHERE r2.city = 'Dallas' AND r2.cuisine = r.cuisine
);
Practice tip: This NOT IN + NULL interaction is a genuinely famous SQL gotcha — it has caused real production bugs at companies with otherwise experienced teams. You'll meet NOT EXISTS properly once subqueries are covered in Chapter 5; for now, just remember that NOT IN and NULL don't mix safely.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it's published, and share it with a developer who'd find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server Fundamentals, coming soon on this site.