1The NULL Difference
COUNT(*) counts the number of ROWS in the table, regardless of what's in them. COUNT(email) counts the number of rows where the email column is NOT NULL. If 10 users haven't provided an email, COUNT(*) might be 100, while COUNT(email) will be 90.
2Step-by-Step Breakdown
The Wrong Way. If you want to know how many users you have, DO NOT fetch all 1 million users to Node.js and run 'users.length'. That transfers gigabytes of data just to get one number.
The Right Way. Use SQL Aggregate Functions. They process millions of rows directly on the database's hard drive and return a single, tiny number to Node.js.
COUNT(). Returns the number of rows. 'SELECT COUNT(*) FROM users;'. This returns a single row with a single column containing the total number.
SUM(). Adds up all the values in a numeric column. 'SELECT SUM(price) FROM orders WHERE status = 'paid';'. Instantly calculates total revenue.
Knowledge Check. If a column contains NULL values, how do aggregate functions like AVG() or SUM() treat those rows?
- →They treat them as the number 0
- →They completely ignore them
AVG(). Calculates the mathematical average. 'SELECT AVG(age) FROM users;'. Because it ignores NULLs, it only averages users who actually provided an age.
MIN() and MAX(). Finds the lowest or highest value in a column. This works for numbers, but also for Dates! 'SELECT MAX(created_at) FROM users;' finds the newest user's date.
Combining Aggregates. You can run multiple aggregates in one query. 'SELECT COUNT(*), SUM(price), AVG(price) FROM orders;'. This generates a complete dashboard report instantly.
The Rule of Aggregates. If you use an aggregate function like SUM(), you CANNOT also select a normal column like 'name' in the same query... unless you use GROUP BY (which we learn next).
Summary. Never transfer raw data to Node if you only need the math result.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Dashboard Numbers Need More Than a Big Font
A stat card showing 'SELECT COUNT(*) FROM orders' as a giant number is meaningless to a screen reader unless it's paired with a text label (e.g. aria-label="Total orders: 1,204") — visual size alone conveys nothing to non-sighted users.
SEO Implications
- 1
Aggregate Queries Power Stats That Search Engines Crawl
Pages showing counts like '1,204 products in stock' or 'Average rating: 4.7' should compute those with COUNT()/AVG() server-side and render them in the initial HTML, since crawlers reading only static markup won't wait for a client-side fetch to populate the number.
Best Practices
Push the Math to the Database, Not to Node.js
Never fetch every row into Node just to call .length or manually sum a field — SELECT COUNT(*) or SELECT SUM(price) processes millions of rows on the server's hard drive and returns one tiny number, instead of transferring gigabytes over the wire.
Choose COUNT(*) vs COUNT(column) Deliberately
COUNT(*) counts every row regardless of content, while COUNT(email) counts only rows where email is NOT NULL — mixing these up silently gives you the wrong total whenever a column has missing values.
Frequent Bugs
A report shows an average that seems too high because rows with a NULL score were expected to count as zero.
AVG() and SUM() silently ignore NULL values rather than treating them as 0 — if you need NULLs counted as zero, wrap the column in COALESCE(score, 0) before aggregating.
Real-World Examples
Building a Revenue Dashboard in One Query
An admin dashboard needed total orders, revenue, and average order value without pulling every order row into the Node.js API layer.
SELECT COUNT(*) AS total_orders, SUM(price) AS revenue, AVG(price) AS avg_order_value
FROM orders
WHERE status = 'paid';