2010-04-05 12 views
1

J'ai une table nommé statsComment implémenter un système pour déterminer si une étape importante a été atteinte

 
player_id team_id match_date goal assist` 
     1  8 2010-01-01 1  1 
     1  8 2010-01-01 2  0 
     1  9 2010-01-01 0  5 
    ... 

Je voudrais savoir quand un joueur atteint une étape importante (par exemple, 100 buts, 100 passes, 500 buts. ..)
Je voudrais savoir aussi quand une équipe atteint un jalon.
Je veux savoir quel joueur ou équipe atteint 100 buts en premier, deuxième, troisième ...

Je pensais utiliser des déclencheurs avec des tables pour accumuler les totaux.
Tableau player_accumulator (et team_accumulator) table serait

 

player_id total_goals total_assists 
     1   3    6 


team_id total_goals total_assists 
     8    3    1 
     9    0    5 

Chaque fois qu'une ligne est insérée dans le tableau de statistiques, un déclencheur insérer/mise à jour et les tables de player_accumulator team_accumulator.
Ce déclencheur peut également vérifier si le joueur ou l'équipe a atteint une étape importante dans le tableau d'étape contenant des nombres

 
milestone 
     100 
     500 
    1000 
     ... 

Une player_milestone table serait contiennent les jalon atteint par le joueur:

 
player_id stat milestone   date 
     1 goal   100 2013-04-02 
     1 assist  100 2012-11-19 


Il y a une meilleure moyen de mettre en œuvre un «jalon»?
Il y a un moyen le plus simple sans déclencheurs?

J'utilise PostgreSQL

Répondre

3

Je venais compte tous les buts et de passes d'un joueur qui marque, et son équipe, qui marque.

Comme ce côté client (en pseudocode):

function insert_stat(player_id, team_id, match_date, goals, assists) 
{ 
    if (goals>0) { 
    player_goals_before = query('select count(goal) from stats where player_id=?',player_id); 
    team_goals_before = query('select count(goal) from stats where team_id=?',team_id); 
    } 
    if (assists>0) { 
    player_assists_before = query('select count(assist) from stats where player_id=?',player_id); 
    team_assists_before = query('select count(assist) from stats where team_id=?',team_id); 
    } 
    query("insert into stats (player_id, team_id, match_date, goal, assist)\n" 
    +"values (?, ?, ?, ?, ?)", player_id, team_id, match_date, goal, assist); 

    if (goals>0) { 
    if (has_milestone(player_goals_before+goals) and !has_milestone(player_goals_before)) { 
     alert("player " + player_id + " reached milestone!") 
    } 
    if (has_milestone(team_goals_before+goals) and !has_milestone(team_goals_before)) { 
     alert("team " + team_id + " reached milestone!") 
    } 
    } 
    // etc 
} 

Ne pas maintenir la table d'étape, car cela rend la base de données dénormalisé. Je pense que c'est une optimisation prématurée. Seulement quand ce n'est pas assez rapide (par exemple quand les stats auront plus de quelques milliers de lignes par player_id ou team_id) alors vous pouvez penser à maintenir la table des jalons.

+0

Belle idée mais je dois recalculer tous les points pour savoir si le nouveau jalon atteint est le premier, le second ... –

+0

Si cela est trop lent pour vous, vous pouvez le dénormaliser mais avec beaucoup plus de facilité pour maintenir les tables: player_milestones (player_id , milestone_type, date) et team_milestones (team_id, milestone_type, date) dans un trigger. Vous devrez également penser à la concurrence - par exemple, ce qui se passera quand le client1 compte les objectifs, alors le client2 compte les objectifs, puis le client1 insère les statistiques puis les insertions client2 - vous pouvez ainsi manquer le jalon. Je pense que vous aurez besoin d'un niveau d'isolation sérialisable et soyez prêt à réessayer. – Tometzky