Filtering rows with WHERE
Keep only the rows you want with comparisons, AND, OR and NOT, ranges with BETWEEN, lists with IN, and patterns with LIKE. Plus the precedence rule that catches everyone once.
WHERE holds a condition that SQL Server tests against every row from the FROM clause. Rows where it is true are kept; the rest are dropped before the SELECT list is worked out.
| Operator | Meaning | Example |
|---|---|---|
= | CategoryId = 3 | |
<> or != | Unit <> N'each' | |
< <= | Price <= 10 | |
> >= | AddedOn >= '2023-05-01' | |
BETWEEN a AND b | Price BETWEEN 5 AND 10 | |
IN (…) | CategoryId IN (3, 4) | |
LIKE | Name LIKE N'%paint%' | |
IS NULL | Email IS NULL |
Comparing numbers, text and dates
SELECT Name, StockFROM dbo.ProductsWHERE Stock = 0;Name Stock ---------------- ----- Wall plugs (100) 0 Safety goggles 0
N'BAG' finds bag. Dates compare in calendar order, as long as the column is a real date type:
SELECT Name, Unit, AddedOnFROM dbo.ProductsWHERE Unit = N'BAG' OR AddedOn >= '2023-06-01';Name Unit AddedOn ------------------ ---- ---------- Cement 25 kg bag 2023-03-10 Sand 25 kg bag 2023-03-10 Masonry paint 10 L tin 2023-06-12 Paint roller set each 2023-06-12 Safety goggles each 2023-07-01
AND, OR and the precedence trap
AND is true only when both sides are true; OR is true when either side is. When you mix them, AND is applied first, just as × comes before + in arithmetic. Say you want tools or paint, but only the expensive ones:
-- Wrong: read as CategoryId = 1 OR (CategoryId = 5 AND Price > 20)SELECT Name, CategoryId, PriceFROM dbo.ProductsWHERE CategoryId = 1 OR CategoryId = 5 AND Price > 20;Name CategoryId Price ------------------ ---------- ----- Claw hammer 1 18.50 Cordless drill 1 89.00 Tape measure 8 m 1 9.75 Masonry paint 10 L 5 54.00
SELECT Name, CategoryId, PriceFROM dbo.ProductsWHERE (CategoryId = 1 OR CategoryId = 5) AND Price > 20;Name CategoryId Price ------------------ ---------- ----- Cordless drill 1 89.00 Masonry paint 10 L 5 54.00
IN and BETWEEN
IN is a short way to write several = tests joined by OR. BETWEEN is a range that includes both ends. Both have a NOT form.
SELECT Name, CategoryId, PriceFROM dbo.ProductsWHERE CategoryId IN (3, 4) AND Price BETWEEN 4.50 AND 11.90;Name CategoryId Price ----------------- ---------- ----- Timber 2x4 2.4 m 3 6.80 Wood screws (200) 4 11.90 Wall plugs (100) 4 4.50
Patterns with LIKE
| Wildcard | Matches | Example | Finds |
|---|---|---|---|
% | N'%paint%' | ||
_ | N'_and%' | ||
[abc] | N'[CT]%' | ||
[^abc] | N'[^A-S]%' |
SELECT NameFROM dbo.ProductsWHERE Name LIKE N'[CT]%' AND Name NOT LIKE N'%kg';Name ---------------- Claw hammer Cordless drill Tape measure 8 m Timber 2x4 2.4 m
% forces SQL Server to check every row, because an index cannot help find text in the middle of a value. On a few thousand rows that is fine; on millions, it is the first thing to look at when a search is slow.
Name, Price and Stock.
Show a hint
Show the solution
SELECT Name, Price, StockFROM dbo.ProductsWHERE CategoryId IN (3, 4) AND Price < 10 AND Stock > 0;Name Price Stock ---------------- ----- ----- Timber 2x4 2.4 m 6.80 500
Remember
WHERE tests every row and keeps only those where the condition is true. AND is applied before OR; use parentheses whenever you mix them. IN (…)is a list of=tests;BETWEEN a AND bincludes both ends.LIKEpatterns:%any run of characters,_one character,[…]one from a set.Text comparisons follow the collation, usually case-insensitive; dates need real date columns and 'yyyy-mm-dd'literals.