Problems / Null-Safe Aggregation / Editorial
product_id
AVG(rating)
COUNT(rating)
COUNT(*)
rated_count = COUNT(rating)
missing_count = COUNT(*) - COUNT(rating)
COUNT(*) vs COUNT(column) is one of the most common interview traps. COUNT(*) counts rows; COUNT(column) counts non-NULL values in that column. Every other aggregate (AVG, SUM, MIN, MAX) also skips NULLs, which is why AVG(rating) divides by COUNT(rating) — not the row count — and why a product with zero rated reviews yields NULL, not 0. If you ever need the "treat missing as 0" behavior instead, you must opt in explicitly with AVG(COALESCE(rating, 0)).
COUNT(column)
AVG
SUM
MIN
MAX
NULL
0
AVG(COALESCE(rating, 0))
In PySpark the same distinction shows up as F.count("rating") (skips NULLs) vs F.count(F.lit(1)) (all rows).
F.count("rating")
F.count(F.lit(1))
Solve Null-Safe Aggregation yourself →