代码之家  ›  专栏  ›  技术社区  ›  BenAlabaster

如何加入“最新”记录?

  •  1
  • BenAlabaster  · 技术社区  · 14 年前

    我需要对这些表执行一个联接,这样就只联接每个子表的最新条目。

    有人能给我一些提示我怎么做吗?

    3 回复  |  直到 14 年前
        1
  •  3
  •   Laramie    14 年前

    这是我找到的最优化的方法。我针对几种结构进行了测试,与其他方法相比,这种方法具有最低的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
    
        2
  •  3
  •   Ian Clelland    14 年前

    如果您有一个表,其中只包含每个父项的最新条目和父项的id,那么就很简单了,对吧?

    您可以通过将子表连接到表本身来创建这样的表,每个父id只取最大日期戳

       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
    

    获取子表中不存在更高时间戳的父id的所有行。可以在子查询中使用该表来联接到:

       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
  •  2
  •   josephj1989    14 年前

    使用此查询作为基础 注意,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