Как мне присоединиться к «самым последним» записям? - PullRequest
1 голос
/ 22 июня 2010

У меня есть две таблицы в базе данных SQL Server 2000, соединенные родительскими и дочерними отношениями. В дочерней базе данных уникальный ключ состоит из родительского идентификатора и метки даты.

Мне нужно объединить эти таблицы так, чтобы объединялась только самая последняя запись для каждого дочернего элемента.

Кто-нибудь может дать мне какие-нибудь советы, как я могу это сделать?

Ответы [ 3 ]

3 голосов
/ 22 июня 2010

Если бы у вас была таблица, которая только что содержала самую последнюю запись для каждого родителя и идентификатор родителя, то это было бы легко, верно?

Вы можете создать такую ​​таблицу, присоединив дочернюю таблицу к себе, взяв только максимальную дату для каждого родительского идентификатора. Примерно так (ваш диалект SQL может отличаться):

   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

Это возвращает вам все строки в дочерней таблице, для которых не существует более высокой отметки времени, для этого родительского идентификатора. Вы можете использовать эту таблицу в подзапросе, чтобы присоединиться к:

   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

или присоединить родительскую таблицу непосредственно к ней:

   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
3 голосов
/ 22 июня 2010

Вот самый оптимизированный способ, который я нашел для этого. Я проверил его на нескольких структурах, и таким образом IO был самым низким по сравнению с другими подходами.

Этот образец получит последнюю редакцию статьи

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
1 голос
/ 22 июня 2010

Используйте этот запрос в качестве основы Обратите внимание, что определение CTE не является частью запроса, поэтому решение простое

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
...