rss
twitter
    @docwisdom huh?

SUM() cool stuff

One of my personal projects is an on-line football pool that is run by a fried of mine.  The pool is fairly simple, you pick 2 teams each week who you think will have the highest margin of victory (MOV), the person who has the highest aggregate MOV at the end of the season wins.

I was working on a 'stats' page yesterday to show information about the teams chosen by the entrants, as well as MOV information based on team, conference, division, etc... and ran into a potential issue with my database structure.

I have a 'game' table, which has the following columns: gameID, SeasonID, week, homeTeamID, awayTeamID, homeScore, awayScore.  The potential issue was that for any given week, a team could be in the awayTeamID column, or the homeTeamID column.  It was easy enough to determine this by using a CASE...WHEN statement in my SQL.

view plain print about
1...
2CASE WHEN team.teamID = awayTeamID THEN stuff for away team
3ELSE some stuff for home team

There was one problem with this, one of the 'reports' I was working on required the season-long MOV for every team, which means I needed to use SUM().  I know I could have handled this in CF, but I prefer to let the database do what it is good at, and try to avoid unnecessary processing of data with CF.

On a whim, I decided to try something rather odd, and surprisingly, it worked.  I tried putting the case statement inside the SUM() call, like this.

view plain print about
1...
2SUM(
3     CASE WHEN t.teamid = gh.homeTeamID THEN gh.homeScore-gh.awayScore
4     ELSE gh.awayScore-gh.homeScore
5     END
6     ) AS MOV
7...

Basically what this does is use the CASE statement to determine if the team is the home team, if so, it calculates the MOV as homeScore-awayScore.  If the team is not the home team, they must be the away team, so the MOV is calculated as awayScore-homeScore.

I think its pretty cool that you can put logic inside of the SUM() call.  I have not tested it, but I would imagine you could also add logic inside other aggregate functions like MAX() or MIN().

6 comments

(Comment Moderation is enabled. Your comment will not appear until approved.)
Raymond Camden said...
I'm constantly amazed by what can be done in SQL.
todd said...
I LOVE Case. You can pretty much put it _anywhere_ and it will work. My favorite trick is using case to conditionally join tables:

select stuff
from aTable as a
left outer join bTable as b
on case when a.something = 'this' then a.something else a.somethingElse = b.something
Scott Stroz said...
Todd, that is cool ! Of course, now I am going to spend the rest of the day trying to find new places to use CASE.
Seth Petry-Johnson said...
I'm not a DBA, so don't take this as gospel, but the CASE statement might prevent the use of some indices (at best) or lead to a full table scan (at worst). That may not be a huge deal for hobby sites, but I'd pay close attention to the query's execution plan before going hog wild on a production app :)

I do love using CASE when I can get away with it though... in some cases the SQL statement is much, much easier to manage than the alternative.
snekse said...
Dude, I swear you copied my database. You have the exact same structure as I do for my site. I don't think there's anything wrong with the structure. What database are you using? I'm not sure that case statement will be supported in every database - at least in the same way. I do have an if statement in one of my aggregate functions:
Count(IIf(pickscore > 0, 1, Null)) as WCount

The way I tended to get around the same issue was to include the table twice under different aliases. Not sure if it's any better, but it's easier for me to read and wrap my head around.

SELECT g.hometeamscore, g.awayteamscore,h.hometeamname, a.awayteamname
from game g,
(Select teamid as hometeamid, teamcode as hometeamcode, teamname as hometeamname from team ) h,
(Select teamid as awayteamid, teamcode as awayteamcode, teamname as awayteamname from team ) a
where 1=1
AND g.hometeamid = h.hometeamid
AND g.awayteamid = a.awayteamid
Scott Stroz said...
The database is MSSQL.