Hook: Interviewers like SUM because it looks simple, but it quietly tests whether you understand NULL, grouping, and the difference between a total and a row count.
Question: What does SUM do in SQL?
Answer: SUM is an aggregate function that adds numeric values from multiple rows and returns one total. It ignores NULL values, so missing numbers do not get counted. If there are no non-NULL values to add, the result is NULL, not 0.
Interview-Ready Answer: In SQL, I use SUM to add numeric values across rows and get one total back. It ignores NULLs, and I usually pair it with GROUP BY when I need subtotals, like sales per region. One detail I always remember is that if no matching non-NULL rows exist, SUM returns NULL, so I use COALESCE when I need a guaranteed zero.
SUM really isSUM is an aggregate function — a function that compresses many rows into one result. Think of it like a cashier adding every valid receipt into one running total. The input must be numeric or an expression that becomes numeric, such as price * quantity.
WHERE filtering.SUM, such as amount or price * quantity. An expression is just a calculation made from columns and values.NULL, the row is skipped. SUM does not add NULL as if it were zero.NULL values at all, the result is NULL.When you add GROUP BY, the same idea happens once per group. For example, the database may keep one running total for each region, each customer, or each day.
CASE WHEN, such as paid revenue only.| Function | What it does | NULL behavior | Typical use |
|---|---|---|---|
SUM | Adds values | Ignores NULL | Totals |
COUNT(*) | Counts rows | Counts every row | Row totals |
COUNT(col) | Counts non-NULL values | Ignores NULL | Filled values |
AVG | Average value | Ignores NULL | Mean value |
MAX | Largest value | Ignores NULL | Peak value |
AVG is especially useful to compare with SUM: average is essentially SUM divided by the count of non-NULL rows.
The time complexity is usually O(n) over the qualifying rows, because the database must inspect each row that matches the filter. For a single total, memory is usually O(1); for grouped totals, memory is closer to O(g), where g is the number of groups. If there are 100,000 groups, a hash aggregate can use tens of MB or more depending on the engine and row width, and it may spill to disk if memory is too small.
Indexes do not make SUM free. A selective filter can help the engine read fewer rows, but the database still has to add the matching values. On a warm cache, a simple sum over millions of rows may finish in a few hundred milliseconds; on a cold disk, it may take seconds.
Two important engine details vary by database version and dialect:
DECIMAL or NUMERIC, not floating-point types like REAL, because floats can accumulate tiny rounding errors.One more useful variant is SUM(DISTINCT col), which removes duplicate values before adding them. That can be helpful, but it usually costs more because the engine must deduplicate first.
Memory hook: think of SUM as a cash drawer: it adds every valid bill, skips empty envelopes, and if nobody puts money in, the drawer stays blank unless you tape on a zero with COALESCE.
Real-World Story: In an e-commerce checkout service, SUM is used to total line items for each order, such as SUM(price * quantity) grouped by order_id. That total feeds tax calculation, payment authorization, and the final invoice sent to the customer. If the team forgets that SUM returns NULL for an empty result set, a cart with no remaining billable items can produce null in the API instead of 0.
What goes wrong in production is easy to miss at first: the checkout page starts showing a blank total or a frontend error like 'cannot read amount from null'. Logs show entries such as total_amount=null for some orders, and support tickets spike because users cannot complete payment. The bug is not that SUM is broken; it is that the app assumed it would always return a number, so one edge case turned into a failed checkout flow.
-- A small, runnable example showing how SUM behaves in real SQL.
-- The data includes a NULL amount, a duplicate amount, and a negative amount
-- so you can see skipping NULLs, grouping, and DISTINCT behavior clearly.
CREATE TABLE sales (
sale_id INTEGER PRIMARY KEY,
region VARCHAR(20),
amount DECIMAL(10,2),
quantity INTEGER
);
INSERT INTO sales (sale_id, region, amount, quantity) VALUES
(1, 'East', 19.99, 1),
(2, 'East', 10.00, 2),
(3, 'West', NULL, 3),
(4, 'West', 5.50, NULL),
(5, 'North', -2.00, 1),
(6, 'East', 10.00, 1);
-- Basic total: NULL is ignored, so row 3 does not affect the total.
SELECT SUM(amount) AS total_amount
FROM sales;
-- Grouped totals: one running total per region.
SELECT region, SUM(amount) AS region_total
FROM sales
GROUP BY region
ORDER BY region;
-- COUNT(*) counts rows, COUNT(amount) counts only non-NULL amounts,
-- and SUM(amount) adds the actual numbers.
SELECT
COUNT(*) AS rows_seen,
COUNT(amount) AS rows_with_amount,
SUM(amount) AS amount_total
FROM sales;
-- DISTINCT removes duplicate values before the addition.
-- Here, the two 10.00 rows are counted once in the distinct total.
SELECT
SUM(amount) AS normal_sum,
SUM(DISTINCT amount) AS distinct_sum
FROM sales;
-- Failure path: no matching rows means SUM returns NULL.
-- COALESCE turns that NULL into 0 when the application needs a real numeric zero.
SELECT
SUM(amount) AS raw_sum,
COALESCE(SUM(amount), 0) AS safe_sum
FROM sales
WHERE region = 'South';
-- Another edge case: if every matching value is NULL, the raw sum is still NULL.
SELECT
SUM(amount) AS all_null_raw_sum,
COALESCE(SUM(amount), 0) AS all_null_safe_sum
FROM sales
WHERE amount IS NULL;Follow-up & Tricky Questions:
SUM do with NULL values? It ignores them. That is why SUM(amount) and SUM(COALESCE(amount, 0)) can behave differently when you care about missing data.SUM and COUNT? SUM adds numeric values, while COUNT counts rows or non-NULL values. They answer different questions, even though both are aggregates.SUM(CASE WHEN condition THEN value ELSE 0 END). This is the standard pattern for totals like paid revenue, refunded revenue, or active-user minutes.SUM(DISTINCT col) do? It deduplicates values before adding them, so repeated equal values are counted once. It is not the same as summing distinct rows from a GROUP BY.SUM in COALESCE? Because SUM can return NULL for an empty result set. COALESCE gives you a default like 0 when your app needs a real number.SUM in WHERE? No, because WHERE runs before aggregation. Use HAVING for grouped filters, or put the aggregate in a subquery.SUM fix rounding problems automatically? No. If you sum floating-point values, you can still get tiny precision errors. For money, store values as DECIMAL or NUMERIC.SUM over an empty set 0? No, it is NULL. This is one of the most common interview traps.SUM be used in WHERE? No again; it belongs in SELECT or HAVING. The trick is remembering the order of SQL operations.Common Mistakes:
SUM returns NULL when nothing non-NULL is available, so use COALESCE if you need 0.SUM to count rows: correction — use COUNT(*) for rows and COUNT(col) for non-NULL values.DECIMAL or NUMERIC to avoid rounding surprises.SUM in WHERE: correction — aggregate filters belong in HAVING or a subquery because WHERE runs first.Memory Hook: SUM is the cash drawer: it adds every valid bill, skips empty envelopes, and if nobody puts money in, the drawer shows blank unless you paste on a zero with COALESCE.
Cheat Sheet:
SUM adds numeric values across rows.NULL inputs.NULL, not 0.GROUP BY for subtotals.COALESCE(SUM(...), 0) when the app needs a guaranteed number.DECIMAL for currency.Practice Tasks:
NULL, then observe the raw SUM result.