Reputation: 837
I'm trying to generate a summary from a list of scores in SQL Server 2008.
I have two tables: SQL Fiddle link
The ScorePerson
table contains people's ID and their score from -5 to 15. End users of my SQL/Stored Procedure needs to create a summary like this:
Scoreband| TotalNoOfPeople | AvgScore
--------------------------------
-5 to 0 | 2 | -2
0 to 5 | 3 | 2
5 to 10 | 2 | 8
10 to 15 | 3 | 13.3
The score band i.e. the min and max values should be configurable from the ScoreMinMax
table by the end user.
I have tried to achive this using CASE stement, but it generates the summary as columns. I I would probably need to pivot it or use UNION from multiple select statements. But this approach doesn't seem scalable if there were new rows added to the ScoreMinMax
table.
So far I was able to achieve some results similar to the example above using CROSS JOINT, but it doesn't always produces the correct results.
Is anyone able to point me in the right direction on how to achieve this please?
ScorePerson - contains actual scores
ScoreMinMax - the configuration for min and max score bands
Upvotes: 4
Views: 1070
Reputation: 247710
You can use aggregate functions:
select title ScoreBand,
count(*) TotalNoPeople,
avg(p.score) AvgScore
from scoreperson p
inner join scoreminmax m
on p.score between m.minscore and m.maxscore
group by Title
order by cast(left(title, 2) as int)
If you have no person in an existing range, you can us something like this:
select case when title is not null
then title
else 'No Range' end ScoreBand,
count(personid) TotalNoPeople,
avg(p.score) AvgScore
from scoreperson p
left join scoreminmax m
on p.score between m.minscore and m.maxscore
group by id, Title
order by id
edit #2, based on your comments you can use:
select m.title ScoreBand,
count(p.personid) TotalNoPeople,
avg(p.score) AvgScore
from scoreminmax m
left join scoreperson p
on p.score between m.minscore and m.maxscore
group by m.id, m.Title
order by m.id;
Upvotes: 4
Reputation: 51494
Try
Select Title, count(personid), AVG(score)
from
scoreminmax
left join scoreperson
on scoreperson.score>=minscore
and scoreperson.score<maxscore
group by ID,title
order by ID
Note that I have included scores on the boundaries (0,5,10) in only one of the groups.
Upvotes: 1
Reputation: 125254
select smm.Title Scoreband, count(*) TotalNoOfPeople, avg(sp.Score) AvgScore
from
ScorePerson sp
inner join
ScoreMinMax smm on sp.Score >= smm.MinScore and sp.Score < smm.MaxScore
group by smm.Title
Upvotes: 0