MySQL IS NOT NULL
IS NOT NULL selects rows where a column has a value. It is how you find complete records, count filled-in fields and skip unknowns before calculating. It is the opposite of IS NULL.
1. Basic Usage
WHERE column IS NOT NULL
Table: applicants (6 rows)
| id | name | phone | portfolio_url | years_exp | referred_by | |
|---|---|---|---|---|---|---|
| 1 | Asha | asha@mail.example | 98450 10001 | https://asha.dev | 4 | NULL |
| 2 | Ben | ben@mail.example | NULL | https://ben.design | 2 | 1 |
| 3 | Chitra | NULL | 98450 10003 | https://chitra.io | 7 | NULL |
| 4 | Dan | dan@mail.example | 98450 10004 | https://dan.codes | NULL | 3 |
| 5 | Eva | eva@mail.example | 98450 10005 | NULL | 1 | 1 |
| 6 | Farid | NULL | NULL | NULL | 5 | NULL |
SELECT name, portfolio_url FROM applicants WHERE portfolio_url IS NOT NULL;
Result: 4 rows
| name | portfolio_url |
|---|---|
| Asha | https://asha.dev |
| Ben | https://ben.design |
| Chitra | https://chitra.io |
| Dan | https://dan.codes |
2. Why <> NULL Doesn't Work
SELECT name FROM applicants WHERE portfolio_url <> NULL;
<> NULL: always empty
| name |
|---|
| No rows |
SELECT name FROM applicants WHERE NOT (portfolio_url IS NULL);
NOT (… IS NULL): same as IS NOT NULL
| name |
|---|
| Asha |
| Ben |
| Chitra |
| Dan |
3. Combining with Other Conditions
SELECT name, email, phone FROM applicants WHERE email IS NOT NULL AND phone IS NOT NULL; -- fully contactable
Result: 3 rows
| name | phone | |
|---|---|---|
| Asha | asha@mail.example | 98450 10001 |
| Dan | dan@mail.example | 98450 10004 |
| Eva | eva@mail.example | 98450 10005 |
SELECT name, years_exp FROM applicants WHERE years_exp IS NOT NULL AND years_exp >= 4;
Result: 3 rows
| name | years_exp |
|---|---|
| Asha | 4 |
| Chitra | 7 |
| Farid | 5 |
years_exp >= 4 alone already excludes NULLs (NULL >= 4 isn't TRUE). The explicit IS NOT NULL makes the intent clear but isn't required here.4. COUNT(column) Counts Non-NULL Values
SELECT COUNT(*) AS applicants,
COUNT(email) AS with_email,
COUNT(phone) AS with_phone,
COUNT(portfolio_url) AS with_portfolio,
COUNT(referred_by) AS referred
FROM applicants;
Result: 1 row
| applicants | with_email | with_phone | with_portfolio | referred |
|---|---|---|---|---|
| 6 | 4 | 4 | 4 | 3 |
A data-completeness report as percentages:
SELECT ROUND(100 * COUNT(email) / COUNT(*)) AS email_pct,
ROUND(100 * COUNT(phone) / COUNT(*)) AS phone_pct,
ROUND(100 * COUNT(portfolio_url) / COUNT(*)) AS portfolio_pct
FROM applicants;
Result: 1 row
| email_pct | phone_pct | portfolio_pct |
|---|---|---|
| 67 | 67 | 67 |
5. Counting Filled Fields per Row
IS NOT NULL returns 1 or 0, so you can add the results to score each record:
SELECT name,
(email IS NOT NULL) + (phone IS NOT NULL) + (portfolio_url IS NOT NULL) + (years_exp IS NOT NULL) AS fields_filled
FROM applicants
ORDER BY fields_filled DESC, name;
Result: 6 rows
| name | fields_filled |
|---|---|
| Asha | 4 |
| Ben | 3 |
| Chitra | 3 |
| Dan | 3 |
| Eva | 3 |
| Farid | 1 |
6. IS NOT NULL with Joins
After a LEFT JOIN, unmatched rows have NULLs on the right side. IS NOT NULL keeps only the matched ones, here applicants who were referred, with their referrer's name:
SELECT a.name AS applicant, r.name AS referred_by
FROM applicants a
LEFT JOIN applicants r ON r.id = a.referred_by
WHERE a.referred_by IS NOT NULL;
Result: 3 rows
| applicant | referred_by |
|---|---|
| Ben | Asha |
| Dan | Chitra |
| Eva | Asha |
7. IS NOT NULL in UPDATE
UPDATE applicants SET portfolio_url = LOWER(TRIM(portfolio_url)) WHERE portfolio_url IS NOT NULL;
SELECT COUNT(*) AS cleaned FROM applicants WHERE portfolio_url IS NOT NULL;
Result: 1 row
| cleaned |
|---|
| 4 |
8. IS NOT NULL vs the NOT NULL Constraint
IS NOT NULL (condition) | NOT NULL (constraint) | |
|---|---|---|
| Where | In WHERE, SELECT, CASE… | In CREATE / ALTER TABLE |
| What it does | Tests a value when you query | Prevents NULLs from being stored |
| Example | WHERE email IS NOT NULL | email VARCHAR(40) NOT NULL |
If a column should never be empty, enforce it with the NOT NULL constraint rather than filtering later.
9. Practice Exercises
Exercise 1: Applicants with a portfolio but no phone number.
SELECT name FROM applicants WHERE portfolio_url IS NOT NULL AND phone IS NULL;
Result: 1 row
| name |
|---|
| Ben |
Exercise 2: Average experience of applicants whose experience is known, and how many that is.
SELECT COUNT(years_exp) AS known, ROUND(AVG(years_exp), 1) AS avg_years FROM applicants WHERE years_exp IS NOT NULL;
Result: 1 row
| known | avg_years |
|---|---|
| 5 | 3.8 |
10. Summary
IS NOT NULLkeeps rows where the column has a value;<> NULLnever works.- COUNT(column) counts non-NULL values; COUNT(*) counts rows.
- IS NOT NULL returns 1/0, useful for completeness scores.
- Use it after LEFT JOINs to keep matched rows.
- Use the NOT NULL constraint to stop NULLs being stored at all.