Field note · May 9, 2024
The overall average hides 5 different numbers
Real group means for one column across 5 segments, and what the pooled average conceals.
queue splits support-tickets into 5 groups. Here is what first_response_min looks like inside each.
integrations— mean 164, median 92 (525 rows)billing— mean 154, median 80 (960 rows)account— mean 151, median 80 (647 rows)technical— mean 148, median 76 (1,282 rows)onboarding— mean 127, median 77 (586 rows)
Top to bottom that is 164 against 127, a spread of 29.1%. The pooled average is 155.
select queue,
count(*) as rows,
round(avg(first_response_min)::numeric, 2) as mean,
percentile_cont(0.5) within group (order by first_response_min) as median
from support_tickets
group by 1
order by mean desc;The groups are close enough that the pooled average is a fair summary. That is worth confirming rather than assuming: the check costs one query and the failure mode is invisible.
Notice the mean and median columns disagree most in integrations, where the mean sits well above the median. Always compute both in the group-by. The comparison between them per segment is free and tells you whether you are looking at a level difference or a tail difference.
This is the setup for Simpson's paradox — the case where every segment moves one way and the total moves the other.