SQL NULLIF: Syntax, Examples and the Divide-by-Zero Fix
NULLIF(a, b) returns NULL when a equals b, and returns a otherwise. Its best-known use is preventing division-by-zero errors: x / NULLIF(y, 0) gives NULL instead of failing when y is 0. It also turns placeholder values such as 0 or 'N/A' into real NULLs.
What Is NULLIF in SQL?
NULLIF compares two values. If they are equal it returns NULL; if they differ it returns the first value unchanged:
SELECT NULLIF(100, 100) AS same_numbers,
NULLIF(100, 50) AS different_numbers,
NULLIF('SQL', 'SQL') AS same_text,
NULLIF('SQL', 'MySQL') AS different_text;
▶ Run this query in the SQL Playground
| same_numbers | different_numbers | same_text | different_text |
|---|---|---|---|
| NULL | 100 | NULL | SQL |
NULLIF(value1, value2)
-- means exactly the same as
CASE WHEN value1 = value2 THEN NULL ELSE value1 END
| Rule | Meaning |
|---|---|
| Equal | Returns NULL |
| Different | Returns the first argument |
| Order matters | NULLIF(a, b) and NULLIF(b, a) return different values when a and b differ |
| First argument NULL | Returns NULL (there is nothing else to return) |
| Standard SQL | Works the same in PostgreSQL, MySQL, SQL Server, Oracle and SQLite |
Preventing Division by Zero
Dividing by zero is an error in PostgreSQL, SQL Server and Oracle, and stops the whole query. Wrapping the divisor in NULLIF(divisor, 0) turns a zero into NULL first. Anything divided by NULL is NULL, so the row gets a NULL instead of the query failing.
A realistic case: the share of successful payments per payment method. If a method had no payments yet, the divisor would be 0:
SELECT method,
COUNT(*) AS payments,
SUM(status = 'success') AS successful,
ROUND(100.0 * SUM(status = 'success') / NULLIF(COUNT(*), 0), 1) AS success_pct
FROM payments
GROUP BY method
ORDER BY success_pct DESC;
▶ Run this query in the SQL Playground
| method | payments | successful | success_pct |
|---|---|---|---|
| Credit Card | 14 | 12 | 85.7 |
| Google Pay | 13 | 10 | 76.9 |
| PayPal | 24 | 18 | 75 |
| Debit Card | 28 | 21 | 75 |
| Cryptocurrency | 34 | 24 | 70.6 |
| Bank Transfer | 38 | 23 | 60.5 |
| Apple Pay | 27 | 16 | 59.3 |
| Gift Card | 22 | 13 | 59.1 |
Here no method has zero payments, so NULLIF changes nothing; it is there so the query stays safe when the data changes. The next example shows the case where it matters, using the sample rows below (respondents B and E have zero visits):
WITH survey(respondent, city, score, visits) AS (
VALUES ('A', 'Pune', 8, 4),
('B', 'N/A', 0, 0),
('C', 'Delhi', 9, 3),
('D', 'Unknown', 0, 2),
('E', 'Pune', 6, 0)
)
SELECT respondent, score, visits,
ROUND(1.0 * score / NULLIF(visits, 0), 2) AS score_per_visit
FROM survey;
▶ Run this query in the SQL Playground
| respondent | score | visits | score_per_visit |
|---|---|---|---|
| A | 8 | 4 | 2 |
| B | 0 | 0 | NULL |
| C | 9 | 3 | 3 |
| D | 0 | 2 | 0 |
| E | 6 | 0 | NULL |
10 / 0 already returns NULL. NULLIF still matters: it makes the query portable to PostgreSQL and SQL Server, and it states the intent. To show 0 instead of NULL, wrap the result in COALESCE: COALESCE(x / NULLIF(y, 0), 0).Turning Placeholder Values Into NULL
Data often contains values that really mean "unknown": 0 for a missing score, 'N/A' or 'Unknown' for a missing city. Left as they are, they distort counts and averages. NULLIF turns them into NULL, which aggregates skip:
WITH survey(respondent, city, score, visits) AS (
VALUES ('A', 'Pune', 8, 4),
('B', 'N/A', 0, 0),
('C', 'Delhi', 9, 3),
('D', 'Unknown', 0, 2),
('E', 'Pune', 6, 0)
)
SELECT respondent,
NULLIF(NULLIF(city, 'N/A'), 'Unknown') AS city,
NULLIF(score, 0) AS score
FROM survey;
▶ Run this query in the SQL Playground
| respondent | city | score |
|---|---|---|
| A | Pune | 8 |
| B | NULL | NULL |
| C | Delhi | 9 |
| D | NULL | NULL |
| E | Pune | 6 |
NULLIF compares with one value, so two placeholders need two nested calls. For a longer list, a CASE with IN ('N/A', 'Unknown', '-') is easier to read.
Effect on averages and counts
WITH survey(respondent, city, score, visits) AS (
VALUES ('A', 'Pune', 8, 4),
('B', 'N/A', 0, 0),
('C', 'Delhi', 9, 3),
('D', 'Unknown', 0, 2),
('E', 'Pune', 6, 0)
)
SELECT AVG(score) AS avg_with_zeros,
ROUND(AVG(NULLIF(score, 0)), 2) AS avg_without_zeros,
COUNT(NULLIF(city, 'N/A')) AS cities_not_na
FROM survey;
▶ Run this query in the SQL Playground
| avg_with_zeros | avg_without_zeros | cities_not_na |
|---|---|---|
| 4.6 | 7.67 | 4 |
With the zeros counted as real scores the average is 4.6; treating them as missing gives 7.67. Which one is right depends on what 0 means in your data, which is a question to ask before you clean it.
On real Playground data
7 of the 200 orders have a discount of exactly 0. If you want "the average discount among orders that had one", NULLIF removes them from the average:
SELECT SUM(discount = 0) AS no_discount,
ROUND(AVG(discount), 4) AS avg_all_orders,
ROUND(AVG(NULLIF(discount, 0)), 4) AS avg_discounted_orders
FROM orders;
▶ Run this query in the SQL Playground
| no_discount | avg_all_orders | avg_discounted_orders |
|---|---|---|
| 7 | 0.1247 | 0.1292 |
NULLIF With COALESCE
NULLIF and COALESCE work in opposite directions: NULLIF turns a value into NULL, COALESCE turns NULL into a value. Combined, they replace one value with another. Here a 0 score becomes "no score" (NULL) and then a label:
WITH survey(respondent, city, score, visits) AS (
VALUES ('A', 'Pune', 8, 4),
('B', 'N/A', 0, 0),
('C', 'Delhi', 9, 3),
('D', 'Unknown', 0, 2),
('E', 'Pune', 6, 0)
)
SELECT respondent, score,
COALESCE(CAST(NULLIF(score, 0) AS TEXT), 'not answered') AS score_label,
COALESCE(1.0 * score / NULLIF(visits, 0), 0) AS score_per_visit_or_0
FROM survey;
▶ Run this query in the SQL Playground
| respondent | score | score_label | score_per_visit_or_0 |
|---|---|---|---|
| A | 8 | 8 | 2 |
| B | 0 | not answered | 0 |
| C | 9 | 9 | 3 |
| D | 0 | not answered | 0 |
| E | 6 | 6 | 0 |
| Function | Turns | Example |
|---|---|---|
| NULLIF(a, b) | a matching value into NULL | NULLIF(city, 'N/A') |
| COALESCE(a, b, ...) | NULL into the first non-NULL value | COALESCE(city, 'unknown') |
| Both | one value into another | COALESCE(NULLIF(bonus, 0), 1000) |
NULLIF With Text, Dates and CASE
NULLIF works with any type, as long as both arguments are comparable, including text and dates. Here it blanks out the status of orders that are still pending:
SELECT status,
NULLIF(status, 'pending') AS status_after_pending,
COUNT(*) AS orders
FROM orders
GROUP BY status
ORDER BY orders DESC;
▶ Run this query in the SQL Playground
| status | status_after_pending | orders |
|---|---|---|
| delivered | delivered | 82 |
| processing | processing | 28 |
| cancelled | cancelled | 27 |
| pending | NULL | 23 |
| shipped | shipped | 21 |
| refunded | refunded | 19 |
Because NULLIF only tests equality, any other condition needs CASE WHEN. These two expressions are the same:
NULLIF(status, 'pending')
CASE WHEN status = 'pending' THEN NULL ELSE status END
And this one has no NULLIF equivalent, because it tests a range, not equality:
CASE WHEN discount < 0.05 THEN NULL ELSE discount END
NULLIF vs COALESCE, ISNULL, IFNULL and NVL
| Function | Direction | Databases |
|---|---|---|
| NULLIF(a, b) | Value → NULL when a = b | All (standard SQL) |
| COALESCE(a, b, ...) | NULL → first non-NULL value | All (standard SQL) |
| ISNULL(a, b) | NULL → b | SQL Server (MySQL's ISNULL(a) only tests for NULL) |
| IFNULL(a, b) | NULL → b | MySQL, SQLite |
| NVL(a, b) | NULL → b | Oracle |
The names look alike but NULLIF is the only one that creates NULLs. The others all replace them.
Common NULLIF Mistakes
Five errors and how to avoid them.
1. Swapping the arguments
SELECT NULLIF(0, discount)
FROM orders;
SELECT NULLIF(discount, 0)
FROM orders;
NULLIF returns its first argument when the two differ. With the arguments swapped, every order with a discount gets 0.
2. Wrapping the numerator instead of the divisor
SELECT NULLIF(score, 0) / visits
FROM survey;
SELECT score / NULLIF(visits, 0)
FROM survey;
The error comes from the value you divide by, so that is the one that needs NULLIF.
3. Integer division hiding the result
SELECT score / NULLIF(visits, 0)
FROM survey;
SELECT 1.0 * score / NULLIF(visits, 0)
FROM survey;
In SQLite, PostgreSQL and SQL Server, an integer divided by an integer is an integer. Multiply by 1.0 or CAST to get decimals.
4. Expecting NULLIF to replace NULLs
SELECT NULLIF(shipped_date, 'not shipped')
FROM orders;
SELECT COALESCE(shipped_date, 'not shipped')
FROM orders;
NULLIF only creates NULLs. To show a default for a NULL, use COALESCE.
5. Cleaning away a value that is real
-- 0 = "scored zero"
SELECT AVG(NULLIF(score, 0)) FROM tests;
-- keep real zeros
SELECT AVG(score) FROM tests;
If 0 is a genuine result, removing it inflates the average. NULLIF is for placeholders, not for inconvenient values.
NULLIF Cheat Sheet
| Task | Pattern |
|---|---|
| Safe division | x / NULLIF(y, 0) |
| Safe division, 0 instead of NULL | COALESCE(x / NULLIF(y, 0), 0) |
| Decimal result | 1.0 * x / NULLIF(y, 0) |
| Placeholder text to NULL | NULLIF(city, 'N/A') |
| Ignore zeros in an average | AVG(NULLIF(score, 0)) |
| Replace one value with another | COALESCE(NULLIF(bonus, 0), 1000) |
| Count values other than X | COUNT(NULLIF(status, 'test')) |
Practice NULLIF Queries
6 exercises on the real Playground tables.
Write each query yourself first. Every solution has been run against the Playground database.
-
1Easy Show the 8 orders with the smallest discounts, showing NULL instead of 0 for orders without a discount. Table:
ordersShow solution
SELECT id, total, NULLIF(discount, 0) AS discount FROM orders ORDER BY orders.discount, id LIMIT 8;▶ Run this query in the SQL Playground
NULLIF(discount, 0) returns NULL for the zero-discount orders and the discount for the rest.
-
2Easy Count the orders that are not in "pending" status, using NULLIF inside COUNT. Table:
ordersShow solution
SELECT COUNT(NULLIF(status, 'pending')) AS not_pending FROM orders;▶ Run this query in the SQL Playground
Pending rows become NULL and COUNT skips them.
-
3Medium Show each product's margin as a percentage of its cost, safely. Show the 6 highest. Table:
productsShow solution
SELECT name, price, cost, ROUND(100.0 * (price - cost) / NULLIF(cost, 0), 1) AS markup_pct FROM products ORDER BY markup_pct DESC LIMIT 6;▶ Run this query in the SQL Playground
No product has a cost of 0 today, but NULLIF keeps the query safe if one is added.
-
4Medium For the first 8 customers, show the average order value: total spent divided by the number of orders, with 0 for customers who never ordered. Table:
users, ordersShow solution
SELECT u.id, u.first_name, COUNT(o.id) AS orders, COALESCE(ROUND(SUM(o.total) / NULLIF(COUNT(o.id), 0), 2), 0) AS avg_order_value FROM users u LEFT JOIN orders o ON o.user_id = u.id GROUP BY u.id, u.first_name ORDER BY u.id LIMIT 8;▶ Run this query in the SQL Playground
NULLIF protects the division; COALESCE turns the resulting NULL into 0.
-
5Medium Calculate the average helpful votes per review for each rating, ignoring reviews with 0 helpful votes. Table:
reviewsShow solution
SELECT rating, COUNT(*) AS reviews, ROUND(AVG(NULLIF(helpful_votes, 0)), 1) AS avg_votes_when_voted FROM reviews GROUP BY rating ORDER BY rating DESC;▶ Run this query in the SQL Playground
AVG skips the NULLs that NULLIF creates for zero votes.
-
6Hard Per payment method, show the share of payments that were refunded, guarding the division. Table:
paymentsShow solution
SELECT method, SUM(status = 'refunded') AS refunded, COUNT(*) AS payments, ROUND(100.0 * SUM(status = 'refunded') / NULLIF(COUNT(*), 0), 1) AS refund_pct FROM payments GROUP BY method ORDER BY refund_pct DESC;▶ Run this query in the SQL Playground
SUM of a comparison counts the matching rows in SQLite; elsewhere write SUM(CASE WHEN ... THEN 1 ELSE 0 END).
📝 Quiz — NULLIF
Test your understanding · 0/30 answered
What does NULLIF(value1, value2) do?
It is shorthand for CASE WHEN value1 = value2 THEN NULL ELSE value1 END.
What does NULLIF(100, 100) return?
The values are equal.
What does NULLIF(100, 50) return?
They differ, so the first value is returned.
What does NULLIF('SQL', 'SQL') return?
Equal text values give NULL.
What does NULLIF('SQL', 'MySQL') return?
The first argument, unchanged.
How does NULLIF prevent division-by-zero errors?
x / NULLIF(y, 0).
What does amount / NULLIF(quantity, 0) return when quantity is 0?
NULLIF(0, 0) is NULL, and dividing by NULL gives NULL.
Which CASE expression is equivalent to NULLIF(a, b)?
NULL on a match, otherwise the first value.
How are NULLIF and COALESCE related?
They are often combined.
What does COALESCE(NULLIF(bonus, 0), 1000) return when bonus is 0?
NULLIF turns 0 into NULL, then COALESCE supplies 1000.
Can NULLIF be used with text?
Any comparable type works.
Can NULLIF be used with dates?
Equality is all it needs.
How does AVG(NULLIF(score, 0)) differ from AVG(score)?
In the sample survey the average changes from 4.6 to 7.67.
What is the common argument-order mistake?
NULLIF(0, discount) returns 0, not the discount.
Is NULLIF standard SQL?
Unlike ISNULL, IFNULL and NVL.
What does NULLIF(status, 'cancelled') return for a cancelled order?
The values match.
What is the difference in flexibility between NULLIF and CASE WHEN?
Ranges and lists need CASE.
How does SQL Server's ISNULL differ from NULLIF?
Opposite directions.
How does IFNULL relate to NULLIF?
IFNULL exists in MySQL and SQLite.
Why can NULLIF in WHERE hurt performance?
In SELECT it costs almost nothing.
What does EXPLAIN show for a query that uses NULLIF only in SELECT?
The scan and joins are decided by FROM and WHERE.
How do you turn the placeholder 'N/A' into a real NULL?
COALESCE would do the opposite.
How do you compute a click-through rate safely when impressions can be 0?
Multiply by 1.0 for a decimal result.
Which expression gives a bonus of 1000 when the stored bonus is exactly 0?
First 0 becomes NULL, then NULL becomes 1000.
Is NULLIF a common interview topic?
The divide-by-zero question is a classic.
How do analysts typically use NULLIF?
Conversion rates, margins and averages.
What does NULLIF(NULL, NULL) return?
The first argument is NULL, so the result is NULL whatever the comparison says.
Why is NULLIF often preferred to the equivalent CASE?
For anything beyond equality, CASE is still needed.
What is a risk of NULLIF with mismatched types?
Compare like with like.
What does COUNT(NULLIF(status, 'test')) count?
Matching rows become NULL and COUNT skips them.
NULLIF Interview Questions
Q1. What does NULLIF do?
It returns NULL when its two arguments are equal and the first argument otherwise. It is shorthand for CASE WHEN a = b THEN NULL ELSE a END.
Q2. How do you avoid a division-by-zero error?
Wrap the divisor: x / NULLIF(y, 0). The result is NULL when y is 0. Add COALESCE around it if the report should show 0 instead.
Q3. What is the difference between NULLIF and COALESCE?
They work in opposite directions. NULLIF turns a specific value into NULL; COALESCE turns NULL into the first non-NULL value in its list.
Q4. Why might AVG(NULLIF(x, 0)) be wrong?
Only if 0 is a real value. NULLIF is right when 0 is a placeholder for "unknown"; if 0 is a genuine measurement, removing it overstates the average.
Q5. Does SQLite need NULLIF for division by zero?
SQLite returns NULL for division by zero, as MySQL does by default, so the query does not fail. NULLIF is still good practice because PostgreSQL, SQL Server and Oracle raise an error.
Frequently Asked Questions
What is NULLIF in SQL?
NULLIF is a function that compares two values. If they are equal it returns NULL; if they differ it returns the first value. It is most often used to prevent division-by-zero errors.
How does NULLIF work?
NULLIF(value1, value2) checks whether value1 equals value2. If they match it returns NULL; otherwise it returns value1 unchanged.
Why do we use NULLIF?
To turn a specific value, such as a zero divisor or a placeholder like 'Unknown', into NULL, so that division, aggregate functions or COALESCE can handle it correctly.
What is the difference between NULLIF and COALESCE?
NULLIF turns a matching value into NULL. COALESCE does the opposite: it returns the first value in its list that is not NULL. They are often used together.
What is the difference between NULLIF and CASE WHEN?
NULLIF(a, b) means exactly CASE WHEN a = b THEN NULL ELSE a END. It is shorter for that one pattern; any other condition needs CASE WHEN.
How does NULLIF prevent divide-by-zero errors?
NULLIF(divisor, 0) turns a zero divisor into NULL before the division. Dividing by NULL gives NULL instead of an error.
How do data analysts use NULLIF?
To protect ratio calculations such as conversion rates, average order value and margins from division by zero, and to turn placeholder values into NULLs before averaging or counting.
Is NULLIF important in SQL interviews?
Yes. Safe division with NULLIF and combining NULLIF with COALESCE are common practical interview questions.