2010-06-22 7 views
1

J'ai deux tables dans une base de données SQL Server 2000 jointes par une relation parent-enfant. Dans la base de données enfant, la clé unique est composée de l'ID parent et du datestamp.Comment me joindre aux enregistrements "les plus récents"?

Je dois faire une jointure sur ces tables de sorte que seule l'entrée la plus récente pour chaque enfant soit jointe.

Quelqu'un peut-il me donner des conseils sur la façon de procéder?

Répondre

3

Voici le moyen le plus optimisé que j'ai trouvé pour le faire. Je l'ai testé contre plusieurs structures et de cette façon j'avais les plus faibles IO par rapport aux autres approches.

Cet échantillon obtiendrait la dernière révision à un article

SELECT t.* 
FROM ARTICLES AS t 
    --Join the the most recent history entries 
     INNER JOIN REVISION lastHis ON t.ID = lastHis.FK_ID 
     --limits to the last history in the WHERE statement 
      LEFT JOIN REVISION his2 on lastHis.FK_ID = his2.FK_ID and lastHis.CREATED_TIME < his2.CREATED_TIME 
WHERE his2.ID is null 
+0

Merci, ça m'a complètement trié. – BenAlabaster

+0

Je suis content de pouvoir le transmettre. – Laramie

+0

Mighty inefficace O (N^2). Consultez la solution ROW_NUMBER pour la complexité O (N). – wqw

3

Si vous aviez une table qui vient contenait l'entrée la plus récente pour chaque parent, et l'identifiant du parent, il serait facile, non?

Vous pouvez créer une table de cette manière en rejoignant la table enfant sur elle-même, en ne prenant que la date maximum pour chaque identifiant parent. Quelque chose comme cela (votre dialecte SQL peut varier):

SELECT t1.* 
    FROM child AS t1 
LEFT JOIN child AS t2 
     ON (t1.parent_id = t2.parent_id and t1.datestamp < t2.datestamp) 
    WHERE t2.datestamp IS NULL 

qui vous fait toutes les lignes de la table des enfants pour qui n'existe timestamp plus, pour cet ID parent. Vous pouvez utiliser cette table dans une sous-requête pour rejoindre à:

SELECT * 
    FROM parent 
    JOIN (SELECT t1.* 
       FROM child AS t1 
     LEFT JOIN child AS t2 
       ON (t1.parent_id = t2.parent_id and t1.datestamp < t2.datestamp) 
      WHERE t2.datestamp IS NULL) AS most_recent_children 
     ON (parent.id = most_recent_children.parent_id 

ou se joindre à la table parent directement en elle:

SELECT parent.*, t1.* 
    FROM parent 
    JOIN child AS t1 
     ON (parent.id = child.parent_id) 
LEFT JOIN child AS t2 
     ON (t1.parent_id = t2.parent_id and t1.datestamp < t2.datestamp) 
    WHERE t2.datestamp IS NULL 
1

Utilisez cette requête comme base Notez que la définition CTE ne fait pas partie de requête-donc la solution est simple

use test; 
with parent as (
select 123 pid union all select 567 union all 
select 125 union all 
select 789), 
child as(
select 123 pid,CAST('1/12/2010' as DATE) stdt union all 
select 123 ,CAST('1/15/2010' AS DATE) union all 
select 567 ,CAST('5/12/2010' AS DATE) union all 
select 567 ,CAST('6/15/2010' AS DATE) union all 
select 125 ,CAST('4/15/2010' AS DATE) 
) 
select pid,stdt from(
select a.pid,b.stdt,ROW_NUMBER() over(partition by a.pid order by b.stdt desc) selector 
from parent as a 
left outer join child as b 
on a.pid=b.pid) as x 
where x.selector=1 
+1

encore, ne peut pas utiliser cela dans SQL Server 2000 – BenAlabaster

Questions connexes