2008-12-17 9 views
0

J'ai une base de données SQLServer à 3 tables. Lorsqu'une chose est attribuée à un projet, une entrée est placée dans la table ProjectThingLink. Les choses peuvent bouger entre les projets. Le CreatedDate est utilisé pour savoir quel projet a été déplacé pour la dernière fois. J'essaie de créer une liste de tous les projets avec lesquels les choses sont actuellement liées, mais mon cerveau est défaillant.Comment sélectionner uniquement la dernière entrée d'une table?

Existe-t-il un moyen facile de le faire?

Répondre

2
select p.projectName, t.ThingName 
from projects p 
join projectThingLink l on l.projectId = p.projectId 
join thing t on t.thingId = l.thingId 
where l.createdDate = 
(select max(l2.createdDate) 
    from projectThingLink l2 
    where l2.thingId = l.thingId 
); 

REMARQUE: corrigé après commentaire

+0

Je pense qu'il y a un problème avec cette requête. Ne montrera-t-il pas toujours toutes les tâches assignées à un projet même si elles ont été réaffectées? Vous devez supprimer le l2.projectid = l.projectid je pense. –

+0

Merci, je l'ai corrigé maintenant. –

0

Vous pouvez simplement faire

SELECT Project.projectId, Project.ProjectName, ThingName 
FROM Project INNER JOIN ProjectThingLink 
ON Project.ProjectID = ProjectThingLink.ProjectID INNER JOIN 
        Thing ON ProjectThingLink.ThingID = Thing.ThingID 

Will va obtenir une liste de tous les projets avec tout ce qui lui est lié comme ceci:

1 | Project1 | SomeThing

1 | Project1 | ThisThing

2 | Project2 | ThatThing

0
select * from project 
inner join (select projectid, 
        max(createdate) as maxdate 
      from projectThingLink 
      group by projectid) as a 
on projectid = a.projectid and createDate = a.maxDate 
1

Essayez ceci:

select p.ProjectID, p.Name, t.ThingID, t.ThingName, l.CreatedDate 
from Project p 
inner join (
    select ProjectID, max(CreatedDate) as CreatedDate 
    from ProjectThingLink 
    group by ProjectID 
) lm on p.ProjectID = l.ProjectID 
inner join ProjectThingLink l on lm.ProjectID = l.ProjectID and lm.CreatedDate = l.CreatedDate 
inner joing Thing t on l.ThingID = t.ThingID 
2

Cela vous donnera presque toujours de meilleures performances que la méthode de sous-requête. Vous êtes à la recherche essentiellement pour la ligne qui n'a pas d'autres lignes passées plutôt que de chercher la ligne avec la plus grande date:

SELECT 
    P.ProjectID, 
    P.ProjectName, 
    T.ThingID, 
    T.ThingName 
FROM 
    dbo.Projects P 
INNER JOIN dbo.ProjectThingLinks PTL1 ON 
    PTL1.ProjectID = P.ProjectID 
LEFT OUTER JOIN dbo.ProjectThingLinks PTL2 ON 
    PTL2.ProjectID = ThingID = PTL1.ThingID AND 
    PTL2.CreatedDate > PTL1.CreatedDate 
INNER JOIN dbo.Things T ON 
    T.ThingID = PTL1.ThingID 
WHERE 
    PTL2.ThingID IS NULL 

Une fois que vous décidez de vos règles métier pour gérer deux lignes qui ont identiques CreatedDate valeurs que vous pourriez avoir besoin de modifier la requête.

En outre, en note, une table appelée "Things" est généralement un bon signe d'un problème avec la conception de votre base de données. Les tableaux doivent représenter des entités de la vie réelle distinctes. Ce genre de généralité entraînera généralement des problèmes dans le futur. Si ce sont des ressources, ils partageront probablement certains attributs au-delà d'un simple nom. Peut-être que votre cas est un cas très particulier, mais très probablement pas. ;)

+0

J'avais caché un peu les noms de mes tables :) – Loofer

Questions connexes