Using SQL to Aggregate and Calculate Stats
I have shoot 'em game where users compete against each o开发者_StackOverflow社区ther over the course of a week to accumulate the most points. I want to write a query that aggregates statistical data from the shots table. The tables and relationships of concern here are:
- user has many competition_periods
- competition_period belongs to user
- competition_period has many shots
- shot belongs to competition_period
In the shots table I have the following fields to work with:
- result --> string values: WON, LOST or TIED
- amount_won --> integer values: e.g., -100, 0, 2000, etc.
For each user, I want to return a result set with the following aggregated stats:
- won_count
- lost_count
- tied_count
- total_shots_count (won_count + lost_count + tied_count)
- total_amount_won (sum of amount_won)
- avg_amount_won_per_shot (total_amount_won / total_shots_count)
I've worked on this query for few hours now, but haven't made much headway. The statistical functions trip me up. A friend suggested that I try to return the results in a new virtual table called shot_records.
Here is the basic solution, computing the statistics across all shots for a given player (you didn't specify if you want them on a per-competition-period basis or not):
SELECT user, SUM(IF(result = 'WON', 1, 0)) AS won_count,
SUM(IF(result = 'LOST', 1, 0)) AS lost_count,
SUM(IF(result = 'TIED', 1, 0)) AS tied_count,
COUNT(*) AS total_shots_count,
SUM(amount_won) AS total_amount_won,
(SUM(amount_won) / COUNT(*)) AS avg_amount_won_per_shot
FROM user U INNER JOIN competition_periods C ON U.user_id = C.user_id
INNER JOIN shots S ON C.competition_period_id = S.competition_period_id
GROUP BY user
Note that this includes negatives in calculating the "total won" figure (that is, the total is decreased by losses). If that's not the correct algorithm for your game, you would change SUM(Amount)
to SUM(IF(Amount > 0, Amount, 0))
in both places it occurs in the query.
精彩评论