2009-07-29 5 views
0

Nous utilisons un système de gestion de projet en ligne, et j'essaie de l'étendre un peu.Assistance avec requête multi-table SQL - renvoi des résultats en double

Il a les tables d'intérêt suivants:

 
todo_itemStatus: 
+--------------+-----------------------+------+-----+---------------------+----------------+ 
| Field  | Type     | Null | Key | Default    | Extra   | 
+--------------+-----------------------+------+-----+---------------------+----------------+ 
| itemStatusId | bigint(20) unsigned | NO | PRI | NULL    | auto_increment | 
| itemId  | int(10) unsigned  | NO | MUL | 0     |    | 
| statusDate | datetime    | NO |  | 0000-00-00 00:00:00 |    | 
| statusKey | tinyint(3) unsigned | NO |  | 0     |    | 
| memberId  | mediumint(8) unsigned | NO |  | 0     |    | 
+--------------+-----------------------+------+-----+---------------------+----------------+ 

Ce tableau garde la trace quand une tâche est terminée, et maintient également l'état de tous les changements de la tâche.

Il existe alors une table de projet et une table 'article' (ou tâche).

Je veux essentiellement être en mesure d'extraire une liste de projets, avec des détails sur le pourcentage de tâches terminées. Cependant, pour l'instant je serais heureux si je pouvais juste énumérer chaque tâche dans un projet avec des détails sur s'ils sont complets. Pour autant que je sache, la meilleure façon d'obtenir le statut le plus récent d'une tâche est de choisir un todo_itemStatus où le statusDate est le plus récent, ou le itemStatusId est le plus grand alors que itemId est égal à la tâche que je suis. intéressé.

J'ai essayé une requête comme ceci:

<pre> 
select todo_item.itemId, todo_item.title, todo_itemStatus.statusKey, todo_itemStatus.statusDate 
from todo_item, todo_project, todo_itemStatus 
where todo_item.projectId = todo_project.projectId 
and todo_project.projectId = 13 
and todo_itemStatus.itemId = todo_item.itemId 
and todo_itemStatus.statusDate = (
    select MAX(todo_itemStatus.statusDate) 
    from todo_itemStatus key1 where todo_itemStatus.itemId = key1.itemId); 
</pre> 

Cependant, cela donne toutes les mises à jour d'état avec une sortie comme ceci:

 
+--------+-----------------------------------------------------------------------------+-----------+---------------------+ 
| itemId | title                  | statusKey | statusDate   | 
+--------+-----------------------------------------------------------------------------+-----------+---------------------+ 
| 579 | test complete item - delete me            |   1 | 2009-07-28 13:04:38 | 
| 579 | test complete item - delete me            |   0 | 2009-07-28 14:12:12 | 
+--------+-----------------------------------------------------------------------------+-----------+---------------------+ 

Ce qui est pas ce que je veux, comme je veux seulement un entrée de tâche retournant avec le statusKey/statusDate de l'entrée la plus récente dans la table todo_itemStatus.

Je sais que j'ai été un peu vague dans ma description, mais je n'ai pas voulu écrire un message massivement long. Je peux fournir beaucoup plus de détails si nécessaire.

S'il vous plaît quelqu'un peut-il suggérer ce que je fais mal? Cela fait longtemps que je n'ai pas fait de base de données, donc je ne sais pas très bien ce que je fais ici ...

Merci beaucoup! Dave

Répondre

0

J'ai expérimenté un peu plus et la requête suivante fait ce que je veux:

 
select todo_item.itemId, todo_item.title, todo_itemStatus.statusKey, todo_itemStatus.statusDate from todo_itemStatus, todo_item where todo_item.itemId = todo_itemStatus.itemId and todo_item.projectId = 13 and todo_itemStatus.statusDate = (select MAX(status.statusDate) from todo_itemStatus as status where status.itemId = todo_item.itemId); 

Je suis maintenant heureux. Merci pour toute l'aide et les suggestions.

Dave.

1

Vous devriez regarder en utilisant le mot-clé DISTINCT (Microsoft SQL Server)

EDIT: Je viens de relire votre question et je pense que la clause GROUP BY est plus adapté à cette situation. Vous devriez lire http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/, mais essentiellement ce que vous devez faire est de sélectionner d'abord les colonnes que vous êtes intéressé à utiliser une clause GROUP BY:

SELECT todo_itemStatus.itemStatusId, MAX(todo_itemStatus.statusDate) 
FROM todo_item, todo_project, todo_itemStatus 
WHERE todo_item.projectId = todo_project.projectId 
AND todo_itemStatus.itemId = todo_item.itemId 
AND todo_project.projectId = 13 
GROUP BY itemStatusId 

Nous avons ensuite autojointure à cet ensemble de id pour obtenir le reste de les colonnes nous intéressent:

SELECT 
    todo_item.itemId, 
    todo_item.title, 
    todo_itemStatus.statusKey, 
    todo_itemStatus.statusDate 
FROM todo_item 
JOIN todo_itemStatus 
ON todo_itemStatus.itemId = todo_item.itemId 
JOIN 
    (SELECT todo_itemStatus.itemStatusId, MAX(todo_itemStatus.statusDate) 
    FROM todo_item, todo_project, todo_itemStatus 
    WHERE todo_item.projectId = todo_project.projectId 
    AND todo_itemStatus.itemId = todo_item.itemId 
    AND todo_project.projectId = 13 
    GROUP BY itemStatusId) AS x 
ON todo_itemStatus.itemStatusId = x.itemStatusId 
+0

Salut, merci, mais je ne pense pas que DISTINCT fera ce que je veux. Le problème est qu'ils sont plusieurs entrées todo_itemStatus par todo_item, et je veux juste obtenir le plus récent. Je pourrais toutefois avoir tord...mais un test rapide a juste donné une erreur ... – DaveS

+0

Ouais, relisez juste votre question et je pense qu'en fait un GROUP BY est ce qui est nécessaire - essayant de trouver quelque chose pour vous atm. – Justin

+0

Merci pour cela. Je vais jeter un coup d'oeil à cet article, puis relire votre message et vous laisser savoir comment je m'entends. Je vous remercie! – DaveS

Questions connexes