<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. SQL
  3. Foundations
All lessons in this course

Lesson 4 of 54 15 minBeginner

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.

OperatorMeaningExample
=equal toCategoryId = 3
<> or !=not equal toUnit <> N'each'
< <=less than (or equal)Price <= 10
> >=greater than (or equal)AddedOn >= '2023-05-01'
BETWEEN a AND bfrom a to b, both includedPrice BETWEEN 5 AND 10
IN (…)equal to any value in the listCategoryId IN (3, 4)
LIKEmatches a text patternName LIKE N'%paint%'
IS NULLhas no value (next lesson)Email IS NULL
Interactive

Filter BuildMart’s products

Join with
Query.sql
SELECT ProductId, Name, CategoryId, Price, StockFROM dbo.ProductsWHERE Price <= 12.00  AND Stock > 0;
ProductIdNameCategoryIdPriceStock≤12.00Stock>0
11Claw hammer118.5040✗✓
22Cordless drill189.0012✗✓
33Tape measure 8 m19.7565✓✓
44Cement 25 kg27.20300✓✓
55Sand 25 kg24.10220✓✓
66Timber 2x4 2.4 m36.80500✓✓
77Plywood sheet 18 mm342.0080✗✓
88Wood screws (200)411.90150✓✓
99Wall plugs (100)44.500✓✗
1010Masonry paint 10 L554.0025✗✓
1111Paint roller set512.5030✗✓
1212Safety goggles66.800✓✗
AND keeps a row only when every condition is true (all ✓): 5 of 12 rows. Adding conditions with AND can only shrink the result.

Comparing numbers, text and dates

Query.sql
SELECT Name, StockFROM dbo.ProductsWHERE Stock = 0;
Output
Name              Stock
----------------  -----
Wall plugs (100)      0
Safety goggles        0

Text comparisons follow the column’s collation. The default on most servers is case-insensitive, so N'BAG' finds bag. Dates compare in calendar order, as long as the column is a real date type:

Query.sql
SELECT Name, Unit, AddedOnFROM dbo.ProductsWHERE Unit = N'BAG' OR AddedOn >= '2023-06-01';
Output
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:

Query.sql
-- 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;
Output
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

All three tools came back, cheap or not, because the price test was attached only to paint. Parentheses say what you mean:

Query.sql
SELECT Name, CategoryId, PriceFROM dbo.ProductsWHERE (CategoryId = 1 OR CategoryId = 5) AND Price > 20;
Output
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.

Query.sql
SELECT Name, CategoryId, PriceFROM dbo.ProductsWHERE CategoryId IN (3, 4)  AND Price BETWEEN 4.50 AND 11.90;
Output
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

WildcardMatchesExampleFinds
%any run of characters, even noneN'%paint%'Masonry paint 10 L, Paint roller set
_exactly one characterN'_and%'Sand 25 kg
[abc]one character from the setN'[CT]%'names starting with C or T
[^abc]one character not in the setN'[^A-S]%'names starting after S
Query.sql
SELECT NameFROM dbo.ProductsWHERE Name LIKE N'[CT]%' AND Name NOT LIKE N'%kg';
Output
Name
----------------
Claw hammer
Cordless drill
Tape measure 8 m
Timber 2x4 2.4 m

A pattern that starts with % 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.

Quick check

WHERE a = 1 OR b = 2 AND c = 3 is read as…

Quick check

Which prices does Price BETWEEN 6.80 AND 9.75 include?

Quick check

Which names match LIKE N'_a%'?

Practice

A builder wants timber or fixings (categories 3 and 4) that cost under 10 and are in stock. Show Name, Price and Stock.

Show a hint

Combine an IN test, a price test and a stock test with AND. No parentheses are needed when every condition is joined with AND.

Show the solution
Solution.sql
SELECT Name, Price, StockFROM dbo.ProductsWHERE CategoryId IN (3, 4)  AND Price < 10  AND Stock > 0;
Output
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 b includes both ends.
  • LIKE patterns: % 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.
0 of 54 lessons completed