Field note · March 5, 2026
first_response_min by channel: a 11% spread
Real group means for one column across 4 segments, and what the pooled average conceals.
Breaking first_response_min down by channel on support-tickets, because the headline average is 155 and no segment is actually there.
in-app— mean 159, median 81 (952 rows)phone— mean 152, median 85 (489 rows)email— mean 146, median 79 (1,368 rows)chat— mean 143, median 77 (1,191 rows)
Top to bottom that is 159 against 143, a spread of 10.8%. The pooled average is 155.
select channel,
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 in-app, 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.