Sivakanesh
Sivakanesh

Reputation: 837

Generate summary data based on configuration table in SQL Server

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?

SQL Fiddle link

ScorePerson - contains actual scores

Table screenshot

ScoreMinMax - the configuration for min and max score bands

enter image description here

Upvotes: 4

Views: 1070

Answers (3)

Taryn
Taryn

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) 

see SQL Fiddle with Demo

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

see SQL Fiddle with Demo

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;

see SQL Fiddle with Demo

Upvotes: 4

podiluska
podiluska

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

Clodoaldo Neto
Clodoaldo Neto

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

Related Questions