Filtering with WHERE

WHERE keeps each row for which its condition is true, combining comparisons, IN, BETWEEN, LIKE and IS NULL (Functions and Operators) with AND, OR and NOT. Both queries below look right:

Operator precedence, and NOT applied to a NULLSQL
SELECT sku FROM products WHERE category_id = 2 OR category_id = 3 AND price > 40;
SELECT id FROM reviews WHERE product_id IN (1, 6) AND NOT (body LIKE '%chapter%');
Output
+-----------+
| sku       |
+-----------+
| BK-PHP-01 |
| BK-LAR-01 |
| BK-LNX-01 |
| BK-SQL-01 |
+-----------+
4 rows in set (0.000 sec)
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.001 sec)

AND binds tighter than OR, so the 39.90 PHP book got in; with (category_id = 2 OR category_id = 3) parenthesized, three rows return.

NOT of unknown is unknown. Review 5's body is NULL, so the LIKE and its NOT are NULL, and WHERE drops it. Write body IS NULL OR body NOT LIKE '%chapter%' to get both reviews.

BETWEEN is inclusive, and a bare date means midnight, so BETWEEN '2026-05-01' AND '2026-05-18' misses order 5, placed at 22:10 on the 18th. The half-open ordered_at >= '2026-05-01' AND ordered_at < '2026-05-19' finds orders 4 and 5, and, unlike YEAR(ordered_at) = 2026, keeps the column bare for an index (Sargable Predicates).