Module 1: SQL Foundations30 min

Working with NULL

Progress Tracking

Log in to save this lesson and continue from where you left off.

Log in

The Billion Dollar Mistake

NULL is one of the most misunderstood concepts in SQL. It causes bugs, returns unexpected results, and trips up even experienced developers. But once you understand how it works, you can avoid the pitfalls.

What NULL Actually Means

NULL means "unknown" or "missing." It's not zero. It's not an empty string. It's the absence of a value.

Think of it this way:

  • 0 — means "the value is zero"
  • '' (empty string) — means "the value is blank text"
  • NULL — means "we don't know what the value is"

This distinction matters because NULL behaves differently from actual values.

A Real Example

Let's look at our fintech_app_users table:

Table: fintech_app_users
user_iduser_namephone_number
1Emma Johnson8994954670
2Noah Williams7848177904
3Olivia Garcia921-171-1750
4Liam Martinez
5Ava Rodriguez

Some users haven't provided their phone number — those values show up as NULL. We don't know their phone numbers. Maybe they never entered one. Maybe the data was lost. The point is: we don't have a value.

Finding NULL Values: IS NULL

Here's the first surprise: you can't use = to check for NULL.

SQL
-- This does NOT work:
SELECT *
FROM fintech_app_users
WHERE phone_number = NULL;

This query returns nothing, even though we have rows with NULL phone numbers. Why? Because in SQL, NULL = NULL evaluates to... NULL (which is treated as false). Instead, use IS NULL

Users Missing Phone Numbers

Table: fintech_app_users
user_iduser_namephone_number
1Emma Johnson8994954670
2Noah Williams7848177904
3Olivia Garcia921-171-1750
4Liam Martinez
5Ava Rodriguez
1
Users Missing Phone Numbers
View solution

The product team is launching a new WhatsApp notification feature and needs to identify users who haven't provided their phone numbers yet. These users will be shown a prompt to add their contact information. Find all users who have not provided a phone number. Return the `user ID` and `name`.

Tables: fintech_app_users

Excluding NULL Values: IS NOT NULL

To find rows where a value exists, use IS NOT NULL.

2
Find Users Who Have a Phone Number

Find all users who have a phone number on record.

Tables: fintech_app_users

This gives you only rows where phone_number has an actual value.

Wine Varieties Tasted by Roger Voss

Table: winemag_p2
idcountrydescriptiondesignationpointspriceprovinceregion_1region_2taster_nametaster_twitter_handletitlevarietywinery
118040USA bit too soft and thus lacks structure. Shows a good array of wild berry and briary, brambly flavors. Dry and spicy, and ready now.The Convict Rocky Ridge Vineyard8638CaliforniaRockpileSonomaParadise Ridge 2006 The Convict Rocky Ridge Vineyard Zinfandel (Rockpile)ZinfandelParadise Ridge
59743ItalyAromas of toasted oak, vanilla and a confectionary note lead the nose while the palate offers mature Golden Delicious apple, butterscotch and walnut skin alongside bracing acidity.Mongris Riserva8830Northeastern ItalyCollioKerin O'Keefe@kerinokeefeMarco Felluga 2012 Mongris Riserva Pinot Grigio (Collio)Pinot GrigioMarco Felluga
117951USHeavy in alcohol and overripe, but entirely dry, and the black currant, chocolate and pepper flavors will play well against richly sauced barbecue.The Caboose8430CaliforniaAlexander ValleySonomaStarry Night 2007 The Caboose Zinfandel (Alexander Valley)ZinfandelStarry Night
10202FranceFragrant; dusty plum and rose aromas are followed on the palate by very fruity flavors of cherries and apple skins. The fine bead and rich mousse result in a creamy mouthfeel. It's all a bit obvious and simple, but undeniably good.Brut Rosa8783ChampagneChampagneJoe Czerwinski@JoeCzRuinart NV Brut Rosa (Champagne)Champagne BlendRuinart
69268GermanyLayers of plush yellow peach and apricot flavors highlight this easy, crowd-pleasing kabinett. Sunny lemon acidity lends refreshment to the midpalate, cutting through all the ripeness and leading to a brisk finish. Drink now through 2019.Kabinett8815RheinhessenAnna Lee C. IijimaWeinreich 2012 Kabinett Riesling (Rheinhessen)RieslingWeinreich
3
Wine varieties tasted by 'Roger Voss'
View solution

Find wine varieties tasted by 'Roger Voss' and with a value in the 'region_1' column of the dataset. Output unique variety names only.

Tables: winemag_p2

NULL in Comparisons

NULL makes comparisons tricky. Any comparison with NULL returns NULL (treated as false):

SQL
NULL = NULL  -- Returns NULL (not true!)
NULL <> NULL -- Returns NULL (not true!)
NULL > 5     -- Returns NULL
NULL = 'text'-- Returns NULL

This means rows with NULL values are excluded from most WHERE clauses, even when you might not expect it.

NULL Gets Excluded Silently

SQL
-- This misses NULL rows!
SELECT * FROM fintech_app_users
WHERE status != 'active';

-- This catches them:
SELECT * FROM fintech_app_users
WHERE phone_number IS NULL;
Table: techcorp_workforce
idfirst_namelast_namedepartmentsalaryphone_numberjoining_date
1SarahMitchellHR95000555-01012021-03-15
2MichaelChenHR88000555-01022022-06-01
3EmilyRodriguezHR825002021-09-20
4DavidParkHR80000555-01042023-01-10
5LisaThompsonHR650002021-04-05
4
Find Employees Missing Phone Numbers

Find employees with no phone number from `techcorp_workforce` using IS NULL.

Tables: techcorp_workforce

Users with NULL phone numbers are also excluded — because NULL <> '555-1234' evaluates to NULL, not true.

To include NULLs, explicitly check for them. Fix the query by adding OR phone_number IS NULL:

5
Include NULL Rows in Results

Find all users whose phone number is not '555-1234', including users who have no phone number at all.

Tables: fintech_app_users
Always Ask: Should NULLs Be Included?

Whenever you're filtering and NULLs might be involved, ask yourself: "Should NULL rows be included or excluded?" Then write your WHERE clause accordingly.

NULL with AND and OR

NULL follows three-valued logic (true, false, NULL). This affects how AND and OR behave:

The practical takeaway: if any part of your condition might be NULL, the whole condition might not behave as expected.

Handling NULL with COALESCE

COALESCE returns the first non-NULL value from a list. It's useful for replacing NULLs with default values:

6
Try COALESCE

Use COALESCE to display the text No phone for employees with a NULL phone_number.

Tables: fintech_app_users

The original data doesn't change — COALESCE just controls what appears in your results.

COALESCE can take multiple arguments. It returns the first one that isn't NULL:

SQL
COALESCE(phone_number, mobile, email, 'No contact')

This checks phone number first, then mobile, then email, and falls back to 'No contact' if all are NULL.

Common Mistakes

Using = NULL Instead of IS NULL

SQL
-- Wrong:
WHERE department = NULL

-- Correct:
WHERE department IS NULL

Forgetting that NOT IN Excludes NULLs

SQL
-- If the list contains any NULLs, NOT IN returns nothing:
WHERE department NOT IN ('HR', NULL, 'Admin')

-- Correct: remove the NULL from the list, check separately if needed
WHERE department NOT IN ('HR', 'Admin')

Assuming Empty String Equals NULL

SQL
-- These are different:
WHERE name = ''  -- Empty string
WHERE name IS NULL  -- Unknown value

Key Takeaways

  • NULL means unknown or missing — not zero, not empty string.
  • Use IS NULL and IS NOT NULL, never = NULL.
  • Comparisons with NULL return NULL (treated as false).
  • Be explicit about whether NULL rows should be included in your results.
  • Use COALESCE to replace NULLs with default values.

What's Next

You now know how to filter data in all the ways that matter. In the next lesson, you'll learn to control the order of your results with ORDER BY — essential for any "top N" question.