2010-08-10 4 views
1

J'ai deux tables, avec un contenant des enregistrements référençant l'autre:Est-il possible de condenser ces requêtes en une seule?

Goal 
    id (int) 
    name (text) 
    value_mask (text) 

GoalStatus 
    id (int) 
    goal (int) 
    created (datetime) 
    value (text) 

Goal.id == GoalStatus.goal 

Ce que je voudrais faire, est de tirer le dernier enregistrement de la table GoalStatus, pour chaque enregistrement dans le but. En ce moment, la seule façon que je sais comment faire cela est en faisant une requête distincte pour chaque enregistrement dans l'objectif (pseudocode):

goals = db.query("SELECT * FROM Goal") 

foreach (goals as goal): 
    goalStatus = db.query(" 
     SELECT * FROM GoalStatus 
     WHERE goal = " + goal.id + " 
     ORDER BY created DESC 
     LIMIT 1 
    ") 

Est-il possible de condenser cela, donc je ne fais pas un supplément requête pour chaque objectif?

+0

Je pense que ce que vous voulez est comme: http://stackoverflow.com/questions/1537606/mysql-group-by-with-top-n-number-of-each-kind –

+0

et un autre lien aide: allez mysql part http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ –

Répondre

1

Ceci est la question par groupe-maximum. C'est une chose très courante de vouloir faire que SQL ne soit pas facile, donc on le demande beaucoup.

Here's a summary d'approches que vous pouvez prendre. Ils auront des attributs de performance différents et peuvent se comporter différemment lorsque deux lignes partagent la même valeur que le maximum.

Par défaut première approche, je aurais tendance à aller pour une gauche rejoindre null plutôt que d'un sous-requête:

SELECT ... 
FROM Goal 
JOIN GoalStatus AS Gs0 ON Gs0.goal=Goal.id 
LEFT JOIN GoalStatus AS Gs1 ON Gs1.goal=Goal.id AND Gs1.created>Gs0.created 
WHERE Goal.id=(someid) 
AND Gs1.id IS NULL 

c'est-à-dire, joindre les lignes où il n'y a pas d'autre ligne qui a une plus grande created valeur.

+0

Ce lien était génial. Je ne pouvais pas vraiment obtenir votre exemple pour travailler mais la première méthode sur cette page a fonctionné pour moi - merci! – Ross

0

Vous pouvez adhérer sur GoalStatus où il n'y a pas d'autre statut d'objectif avec le même ID d'objectif qui a une date de création plus grande. Assez moche et va probablement mal, mais tout ce que je pouvais penser.

1
select 
     g.*, 
     gs.id GoalStatusID, 
     gs.created, 
     gs.value 
    from 
     goal g inner join goalstatus gs 
      on g.id = gs.goal 
    where 
     gs.created in 
      (select max(gs2.created) 
       from goalstatus gs2 
       where g.id = gs2.goal) 
+0

J'ai fini par utiliser quelque chose de similaire . – Ross

Questions connexes