MySQL NOT
The NOT operator reverses a condition: rows that would have matched are excluded, and rows that wouldn't are included. It is used on its own (NOT condition) and inside other operators: NOT IN, NOT LIKE, NOT BETWEEN, NOT EXISTS and IS NOT NULL.
1. How NOT Works
Table: flats (6 rows)
| flat_id | area | bhk | rent | furnished | pets_ok | listed_on |
|---|---|---|---|---|---|---|
| 1 | Kothrud | 2 | 24000 | 1 | 0 | 2026-02-01 |
| 2 | Baner | 3 | 38000 | 1 | 1 | 2026-02-10 |
| 3 | Kothrud | 1 | 15000 | 0 | NULL | 2026-02-12 |
| 4 | Hadapsar | 2 | 19000 | 0 | 1 | 2026-02-20 |
| 5 | Wakad | 3 | 31000 | NULL | 0 | 2026-03-02 |
| 6 | Baner | 2 | 27000 | 1 | NULL | 2026-03-05 |
SELECT NOT TRUE AS not_true, NOT FALSE AS not_false, NOT NULL AS not_null, NOT (2 > 5) AS not_expr;
Result: 1 row
| not_true | not_false | not_null | not_expr |
|---|---|---|---|
| 0 | 1 | NULL | 1 |
2. NOT on a Condition
SELECT flat_id, area, rent FROM flats WHERE NOT area = 'Baner';
Result: 4 rows
| flat_id | area | rent |
|---|---|---|
| 1 | Kothrud | 24000 |
| 3 | Kothrud | 15000 |
| 4 | Hadapsar | 19000 |
| 5 | Wakad | 31000 |
Use parentheses to negate a whole group of conditions:
SELECT flat_id, area, bhk FROM flats WHERE NOT (area = 'Baner' OR bhk = 1);
Result: 3 rows
| flat_id | area | bhk |
|---|---|---|
| 1 | Kothrud | 2 |
| 4 | Hadapsar | 2 |
| 5 | Wakad | 3 |
3. NOT with Other Operators
SELECT flat_id, area FROM flats WHERE area NOT IN ('Baner', 'Wakad');
Result: 3 rows
| flat_id | area |
|---|---|
| 1 | Kothrud |
| 3 | Kothrud |
| 4 | Hadapsar |
SELECT flat_id, rent FROM flats WHERE rent NOT BETWEEN 20000 AND 30000;
Result: 4 rows
| flat_id | rent |
|---|---|
| 2 | 38000 |
| 3 | 15000 |
| 4 | 19000 |
| 5 | 31000 |
SELECT flat_id, area FROM flats WHERE area NOT LIKE '%d';
Result: 3 rows
| flat_id | area |
|---|---|
| 2 | Baner |
| 4 | Hadapsar |
| 6 | Baner |
SELECT flat_id, pets_ok FROM flats WHERE pets_ok IS NOT NULL;
Result: 4 rows
| flat_id | pets_ok |
|---|---|
| 1 | 0 |
| 2 | 1 |
| 4 | 1 |
| 5 | 0 |
4. NOT with Boolean Columns
For a boolean column you can write NOT furnished. But flat 5's furnished is NULL (unknown), so it appears in neither list:
SELECT flat_id FROM flats WHERE furnished;
furnished
| flat_id |
|---|
| 1 |
| 2 |
| 6 |
SELECT flat_id FROM flats WHERE NOT furnished;
NOT furnished
| flat_id |
|---|
| 3 |
| 4 |
SELECT flat_id FROM flats WHERE furnished IS NOT TRUE;
IS NOT TRUE also catches NULL
| flat_id |
|---|
| 3 |
| 4 |
| 5 |
IS NOT TRUE is TRUE for FALSE and NULL, which is often what "not furnished" should mean in a report.5. De Morgan's Laws
Pushing NOT inside parentheses swaps AND and OR:
| Expression | Equivalent |
|---|---|
NOT (A AND B) | NOT A OR NOT B |
NOT (A OR B) | NOT A AND NOT B |
SELECT flat_id FROM flats WHERE NOT (bhk = 2 AND rent < 25000);
Result: 4 rows
| flat_id |
|---|
| 2 |
| 3 |
| 5 |
| 6 |
SELECT flat_id FROM flats WHERE bhk <> 2 OR rent >= 25000;
Result: 4 rows
| flat_id |
|---|
| 2 |
| 3 |
| 5 |
| 6 |
Same rows. The second form is often easier to read and to index.
6. NOT and NULL Together
Since NOT leaves NULL as NULL, "everything that isn't X" silently misses unknowns. Flats where pets aren't allowed:
SELECT flat_id, pets_ok FROM flats WHERE NOT pets_ok;
Result: 2 rows
| flat_id | pets_ok |
|---|---|
| 1 | 0 |
| 5 | 0 |
Flats 3 and 6 (unknown) are missing. Decide whether unknown should count, and write it explicitly:
SELECT flat_id, pets_ok FROM flats WHERE NOT pets_ok OR pets_ok IS NULL;
Result: 4 rows
| flat_id | pets_ok |
|---|---|
| 1 | 0 |
| 3 | NULL |
| 5 | 0 |
| 6 | NULL |
7. NOT EXISTS
CREATE TABLE visits (flat_id INT, visitor VARCHAR(20), visit_date DATE);
INSERT INTO visits VALUES (1,'Ravi','2026-03-01'),(2,'Sneha','2026-03-02'),(2,'Tara','2026-03-03'),(4,'Ravi','2026-03-04');
SELECT f.flat_id, f.area
FROM flats f
WHERE NOT EXISTS (SELECT 1 FROM visits v WHERE v.flat_id = f.flat_id);
Result: 3 rows
| flat_id | area |
|---|---|
| 3 | Kothrud |
| 5 | Wakad |
| 6 | Baner |
See MySQL EXISTS.
8. The ! Operator
MySQL also accepts ! as a synonym for NOT (deprecated in 8.0 in favour of NOT, and not standard SQL):
SELECT !TRUE AS bang_true, NOT TRUE AS not_true;
Result: 1 row
| bang_true | not_true |
|---|---|
| 0 | 0 |
NOT a = b means NOT (a = b), but !a = b means (!a) = b. Prefer NOT and parentheses.9. Practice Exercises
Exercise 1: Flats that are not 2 BHK and not in Kothrud.
SELECT flat_id, area, bhk FROM flats WHERE NOT (bhk = 2 OR area = 'Kothrud');
Result: 2 rows
| flat_id | area | bhk |
|---|---|---|
| 2 | Baner | 3 |
| 5 | Wakad | 3 |
Exercise 2: Flats not listed in February 2026.
SELECT flat_id, listed_on FROM flats WHERE listed_on NOT BETWEEN '2026-02-01' AND '2026-02-28';
Result: 2 rows
| flat_id | listed_on |
|---|---|
| 5 | 2026-03-02 |
| 6 | 2026-03-05 |
10. Summary
- NOT reverses TRUE and FALSE; NOT NULL is still NULL.
- Use NOT IN, NOT LIKE, NOT BETWEEN, NOT EXISTS and IS NOT NULL for common cases.
- Negating conditions skips rows with NULLs; add
OR col IS NULLor useIS NOT TRUEwhen needed. - De Morgan: NOT (A AND B) = NOT A OR NOT B; NOT (A OR B) = NOT A AND NOT B.
- Prefer NOT over the deprecated !.