Problems / Device Mix as Row Percentages / Editorial
country
COUNT(*)
COUNT(*) FILTER (WHERE device = 'desktop')
SUM(CASE WHEN device = 'desktop' THEN 1 ELSE 0 END)
0.00
100.0 * cnt / COUNT(*)
100.0
100 * cnt / COUNT(*)
The PySpark version is the same shape: one .agg() with three F.round(100.0 * F.sum(F.when(...)) / F.count("*"), 2) expressions.
.agg()
F.round(100.0 * F.sum(F.when(...)) / F.count("*"), 2)
Row-percentage pivots hinge on the fact that an aggregate query can compute the numerator and denominator in the same pass: FILTER/CASE restricts which rows feed one aggregate while COUNT(*) still sees the whole group. The two classic failure modes are both silent — integer division truncating every share to zero, and treating a missing category as NULL instead of an empty count. Conditional counting sidesteps the second automatically: counting zero matching rows is 0, and 100.0 * 0 / total is a clean 0.00.
FILTER
CASE
100.0 * 0 / total
Solve Device Mix as Row Percentages yourself →