Calculating Standings by Results

Using a PHP Framework called Symfony2, I am developing a web application for people who play the video game Fifa to compete against each other in an online competition. It’s on Github: https://github.com/JonnyD/Elite-Fifa-Leagues

In the picture above you can see the UI of the league standings. These values are calculated and stored in a Standings table after every confirmed match. There’s a problem with this and that is storing calculated values breaks normalization. The only time this could be acceptable is in cases where you want to improve performance by not having to re-calculate the values every time you need them.

However, what if I want to find out a teams standing by their Last X Games Played at Home, Last X Games Played Away, or Last X Games Played Combined?

Here’s how I could get Standings by home matches only:

SELECT team.name, home_team_id AS team_id,
    COUNT(*) AS played,
    SUM((CASE WHEN home_score > away_score THEN 1 ELSE 0 END)) AS won,
    SUM((CASE WHEN away_score > home_score THEN 1 ELSE 0 END)) AS lost,
    SUM((CASE WHEN home_score = away_score THEN 1 ELSE 0 END)) AS drawn,
    SUM(home_score) AS goalsFor,
    SUM(away_score) AS goalsAgainst,
    SUM(home_score - away_score) AS goalDifference,
    SUM((CASE WHEN home_score > away_score THEN 3 WHEN home_score = away_score THEN 1 ELSE 0 END)) AS points
FROM matches
INNER JOIN team ON matches.home_team_id = team.id
WHERE league_id = 94
    AND season_id = 82
    AND confirmed IS NOT NULL
GROUP BY home_team_id
ORDER BY POINTS DESC;

Here’s how I could get Standings by Away matches only:

```
SELECT team.name, away_team_id AS team_id,
    COUNT(*) AS played,
    SUM((CASE WHEN away_score > home_score THEN 1 ELSE 0 END)) AS won,
    SUM((CASE WHEN home_score > away_score THEN 1 ELSE 0 END)) AS lost,
    SUM((CASE WHEN home_score = away_score THEN 1 ELSE 0 END)) as drawn,
    SUM(away_score) AS goalsFor,
    SUM(home_score) AS goalsAgainst,
    SUM(away_score - home_score) AS goalDifference,
    SUM((CASE WHEN away_score > home_score THEN 3 WHEN away_score = home_score THEN 1 ELSE 0 END)) AS points
FROM matches
INNER JOIN team ON matches.away_team_id = team.id
WHERE league_id = 94
    AND season_id = 82
    AND confirmed IS NOT NULL
GROUP BY away_team_id
ORDER BY points DESC;

Here’s how I could get Standings by Home and Away matches combined:

SELECT team.name,
       team_id AS team_id,
       COUNT(*) AS played,
       SUM((CASE WHEN team_score > other_team_score THEN 1 ELSE 0 END)) AS won,
       SUM((CASE WHEN team_score < other_team_score THEN 1 ELSE 0 END)) AS lost,
       SUM((CASE WHEN team_score = other_team_score THEN 1 ELSE 0 END)) AS drawn,
       SUM(team_score) AS goalsFor,
       SUM(other_team_score) AS goalsAgainst,
       SUM(team_score - other_team_score) AS goalDifference,
       SUM((CASE WHEN team_score > other_team_score THEN 3
                 WHEN team_score = other_team_score THEN 1
                 ELSE 0 END)) AS points
FROM
    (
        -- LIST TEAM STATS WHEN PLAYED AS HOME_TEAM
        SELECT
             id,
             league_id,
             season_id,
             home_team_id as team_id,
             home_score   as team_score,
             away_score   as other_team_score,
             confirmed
        FROM    matches
        UNION ALL
        -- LIST TEAM STATS WHEN PLAYED AS AWAY_TEAM
        SELECT
             id,
             league_id,
             season_id,
             away_team_id as team_id,
             away_score   as team_score,
             home_score   as other_team_score,
             confirmed
        FROM matches
    ) matches
INNER JOIN team ON matches.team_id = team.id
WHERE league_id = 94
    AND season_id = 82
    AND confirmed IS NOT NULL
GROUP BY team.name, team_id
ORDER BY POINTS DESC;
 

Updating Citadel Schema

Citadel is a Minecraft plugin

Before Update:

-- Citadel 3 Schema
 
CREATE TABLE groups_group (
 `id` INT AUTO_INCREMENT,
 `name` VARCHAR(255) UNIQUE,
 `password` VARCHAR(255),
 `personal` TINYINT(1) DEFAULT 0,
 `status` INT(2) DEFAULT 0,
 `updated` DATETIME,
 `created` DATETIME,
 PRIMARY KEY (id)
);
 
CREATE TABLE groups_member (
 `id` INT AUTO_INCREMENT,
 `name` VARCHAR(32) UNIQUE,
 `updated` DATETIME,
 `created` DATETIME,
 PRIMARY KEY (id)
);
 
CREATE TABLE groups_group_member (
 `member_id` INT,
 `group_id` INT,
 `role` INT DEFAULT 0,
 `updated` DATETIME,
 `created` DATETIME,
 PRIMARY KEY (member_id, group_id)
);
 
ALTER TABLE groups_group_member
ADD FOREIGN KEY (member_id)
REFERENCES groups_member (id);
 
ALTER TABLE groups_group_member
ADD FOREIGN KEY (group_id)
REFERENCES groups_group (id);
 
-- Citadel 3 Upgrade Script
 
-- Migrate members
INSERT INTO groups_member (name, updated, created)
SELECT name, now(), now() FROM member;
 
-- Migrate Groups
INSERT INTO groups_group(name, password, updated, created)
SELECT name, password, now(), now() FROM faction;
 
-- Migrate Personal Groups
UPDATE groups_group
SET personal = 1
WHERE name IN (SELECT name FROM personal_group);
 
-- Migrate Disciplined Groups
UPDATE groups_group g
JOIN faction f on g.name = f.name
SET status = 2
WHERE f.discipline_flags = 1;
 
-- Migrate Group Admins
INSERT INTO groups_group_member(member_id, group_id, role, updated, created)
SELECT gm.id AS member_id, g.id AS group_id, 0, now(), now()
FROM groups_member gm, faction f, groups_group g
WHERE gm.name = f.founder AND g.name = f.name;
 
-- Migrate Group Members
INSERT INTO groups_group_member(member_id, group_id, role, updated, created)
SELECT gm.id AS member_id, g.id AS group_id, 2, now(), now()
FROM faction_member fm, groups_member gm, groups_group g
WHERE gm.name = fm.memberName AND g.name = fm.factionName;
 
-- Migrate Group Moderators
INSERT INTO groups_group_member(member_id, group_id, role, updated, created)
SELECT gm.id AS member_id, g.id AS group_id, 1, now(), now()
FROM moderator m, groups_member gm, groups_group g
WHERE gm.name = m.memberName AND g.name = m.factionName;
 
-- Citadel 3 Schema Selects
SELECT * FROM groups_member;
SELECT * FROM groups_group;
SELECT * FROM groups_group_member;