I'm trying to create this summary statistic table, counting the number of individuals in each category
Agegroup | All | Female | Male
------------------------------------------------
All | 560594 | 34324 | 234244
< 20 | 4324 | 545 | 3456
20 - 30 | 76766 | 3424 | 32428
30 - 40 | 36766 | 764 | 82427
40 - 50 | 46766 | 4324 | 72422
50 - 60 | 66766 | 3424 | 52424
> 60 | 76766 | 43424 | 12423
from this table
PersonID | Age | Sex
----------------------------
A | 43 | F
B | 22 | F
C | 65 | M
D | 33 | F
E | 28 | M
Is this even possible "in one go" with SQL? I experimented with this, but it's not really coming together..
SELECT SUM(CASE WHEN Age < 20 THEN 1 ELSE 0 END) AS [Under 20],
SUM(CASE WHEN Age BETWEEN 20 AND 30 THEN 1 ELSE 0 END) AS [20-30],
SUM(CASE WHEN Age BETWEEN 30 AND 40 THEN 1 ELSE 0 END) AS [30-40]
FROM Persons
I believe the below is the simplest way to achieve this, and also get the row back even if there are no people within that age range. Also since Sex only has 2 possible values you can use NULLIF instead of the case expression.
SELECT [Agegroup] = Name,
[All] = COUNT(Person.PersonID),
[Female] = COUNT(NULLIF(Person.Sex, 'M')),
[Male] = COUNT(NULLIF(Person.Sex, 'F'))
FROM (VALUES
(0, 1000, 'All'),
(0, 20, '< 20'),
(20, 30, '20 - 30'),
(30, 40, '30 - 40'),
(40, 50, '40 - 40'),
(50, 60, '50 - 40'),
(60, 1000, '> 60')
) AgeRange (MinValue, MaxValue, Name)
LEFT JOIN Person
ON Person.Age >= AgeRange.MinValue
AND Person.Age < AgeRange.Maxvalue
GROUP BY AgeRange.Name, AgeRange.MinValue, AgeRange.Maxvalue
ORDER BY AgeRange.MinValue, AgeRange.MaxValue DESC
Example on SQL Fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With