NULL: no value
You met it in lesson 1: some customers left no email, and that cell shows NULL.
1SELECT id, name, email2FROM customers;
| id | name | |
|---|---|---|
| 1 | Ana Silva | [email protected] |
| 2 | Ben Okafor | [email protected] |
| 3 | Chloe Martin | NULL |
| 4 | David Kim | [email protected] |
| 5 | Emma Novak | [email protected] |
| 6 | Farah Khan | NULL |
| 7 | George Brown | [email protected] |
| 8 | Hana Sato | [email protected] |
| 9 | Ivan Petrov | NULL |
| 10 | Julia Costa | [email protected] |
NULL means "no value" or "unknown". It isn't 0, and it isn't the empty text '' either: 0 is a number and '' is a text of length 0, while NULL is nothing at all. This lesson is about how to deal with it.
Finding NULL: IS NULL
To find the customers with no email, write IS NULL:
1SELECT name, email2FROM customers3WHERE email IS NULL;
| name | |
|---|---|
| Chloe Martin | NULL |
| Farah Khan | NULL |
| Ivan Petrov | NULL |
The other way around, IS NOT NULL finds the ones with a value. In the employees table, the employees who have a manager:
1SELECT name, manager_id2FROM employees3WHERE manager_id IS NOT NULL;
| name | manager_id |
|---|---|
| Omar Haddad | 1 |
| Lucia Romero | 1 |
| Tom Becker | 2 |
| Mei Tanaka | 2 |
| Sam Wilson | 3 |
Employee 1, the manager, has no manager of her own: her manager_id is NULL, so she isn't in the result.
= NULL finds nothing
This is the trap beginners fall into most.
How many rows does the result have?
1SELECT name2FROM customers3WHERE email = NULL;
email = NULL gives no error, but it isn't true for any row, so no rows come back. To find NULL, write email IS NULL.
Run it and see:
1SELECT name2FROM customers3WHERE email = NULL;
| name |
|---|
Why? Compare a value with "unknown" and the answer is "unknown" too, not "true". WHERE keeps only the rows where the condition is true, so every "unknown" row is dropped. Even NULL = NULL is "unknown": two unknown things can't be said to be equal.
Not equal skips NULL too
For the same reason, <> doesn't pick the NULL rows either. How many customers have an email that isn't [email protected]?
1SELECT name, email2FROM customers3WHERE email <> '[email protected]';
| name | |
|---|---|
| Ben Okafor | [email protected] |
| David Kim | [email protected] |
| Emma Novak | [email protected] |
| George Brown | [email protected] |
| Hana Sato | [email protected] |
| Julia Costa | [email protected] |
10 customers minus Ana leaves only 6 rows, not 9: the 3 customers with no email are gone too. A comparison with NULL isn't true, and "not equal" isn't either. To count them in, say so:
1SELECT name, email2FROM customers3WHERE email <> '[email protected]' OR email IS NULL;
| name | |
|---|---|
| Ben Okafor | [email protected] |
| Chloe Martin | NULL |
| David Kim | [email protected] |
| Emma Novak | [email protected] |
| Farah Khan | NULL |
| George Brown | [email protected] |
| Hana Sato | [email protected] |
| Ivan Petrov | NULL |
| Julia Costa | [email protected] |
NULL in math
SELECT also works without FROM, to work out a few values directly. Math with NULL gives NULL, and so does a comparison with it ("unknown"):
1SELECT 10 + NULL, NULL * 2, NULL = NULL, NULL IS NULL;| 10 + NULL | NULL * 2 | NULL = NULL | NULL IS NULL |
|---|---|---|---|
| NULL | NULL | NULL | 1 |
Only IS NULL gives a definite answer: 1 means true (MySQL shows true as 1 and false as 0).
Something else instead: COALESCE
When showing a result, you often want NULL replaced by something readable. COALESCE(a, b) uses a if it isn't NULL, and b if it is:
1SELECT name, COALESCE(email, 'no email') AS email2FROM customers;
| name | |
|---|---|
| Ana Silva | [email protected] |
| Ben Okafor | [email protected] |
| Chloe Martin | no email |
| David Kim | [email protected] |
| Emma Novak | [email protected] |
| Farah Khan | no email |
| George Brown | [email protected] |
| Hana Sato | [email protected] |
| Ivan Petrov | no email |
| Julia Costa | [email protected] |
AS email names this column; otherwise its name would be the whole COALESCE(email, 'no email'). The next lesson covers AS.
COALESCE can take several values and uses the first one that isn't NULL. MySQL also has IFNULL(a, b), which takes just two; COALESCE is the standard way and works in every database.
Where NULL sorts
When you sort by a column with NULLs, MySQL treats NULL as the smallest value: first in ascending order, last in descending:
1SELECT name, email2FROM customers3ORDER BY email, id;
| name | |
|---|---|
| Chloe Martin | NULL |
| Farah Khan | NULL |
| Ivan Petrov | NULL |
| Ana Silva | [email protected] |
| Ben Okafor | [email protected] |
| David Kim | [email protected] |
| Emma Novak | [email protected] |
| George Brown | [email protected] |
| Hana Sato | [email protected] |
| Julia Costa | [email protected] |
The 3 NULL emails are all the same, so sorting them by id as well is what fixes their order. Other databases may do the opposite (PostgreSQL and Oracle put NULL last in ascending order).
Practice
Write the query, then press Check. A hint costs nothing; the answer is there when you need it.
Fix it: comparing with NULL
✓This should get the employees who have a manager, with name and manager_id, sorted by id, but it finds no rows. Fix it.
| name | manager_id |
|---|---|
| Omar Haddad | 1 |
| Lucia Romero | 1 |
| Tom Becker | 2 |
| Mei Tanaka | 2 |
| Sam Wilson | 3 |
1SELECT name, manager_id2FROM employees3WHERE manager_id <> NULL4ORDER BY id;
Contact
✓Get the customers in London with two columns, name and contact: contact is the email, or none for customers without one, sorted by id.
| name | contact |
|---|---|
| Ana Silva | [email protected] |
| Chloe Martin | none |
| Hana Sato | [email protected] |
1SELECT name, email2FROM customers3WHERE city = 'London';
Leave no one out
✓Get the name of every customer whose email isn't [email protected], counting the customers with no email too, sorted by id.
| name |
|---|
| Ana Silva |
| Chloe Martin |
| David Kim |
| Emma Novak |
| Farah Khan |
| George Brown |
| Hana Sato |
| Ivan Petrov |
| Julia Costa |
1SELECT name2FROM customers3WHERE email <> '[email protected]';
What you learned
NULLis "no value": not 0 and not empty text.- Find it with
IS NULLandIS NOT NULL;= NULLand<> NULLfind no rows, and give no error. - Comparing or calculating with
NULLgivesNULL;WHEREkeeps only rows where the condition is true, so<>missesNULLrows too. COALESCE(a, b)replacesNULLwith something else; MySQL'sIFNULLworks too, butCOALESCEworks everywhere.- In MySQL,
NULLsorts as the smallest value; other databases may put it last.