我如何加入“最新”记录?

发布于 2024-09-06 18:59:29 字数 133 浏览 2 评论 0原文

我在 SQL Server 2000 数据库中有两个表,通过父子关系连接起来。在子数据库中,唯一键由父 ID 和日期戳组成。

我需要对这些表进行联接,以便仅联接每个子项的最新条目。

谁能给我任何提示我该如何解决这个问题?

I've got two tables in a SQL Server 2000 database joined by a parent child relationship. In the child database, the unique key is made up of the parent id and the datestamp.

I'm needing to do a join on these tables such that only the most recent entry for each child is joined.

Can anyone give me any hints how I can go about this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半透明的墙 2024-09-13 18:59:29

这是我发现的最优化的方法。我针对多种结构对其进行了测试,与其他方法相比,这种方法的 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

Here's the most optimized way I've found to do this. I tested it against several structures and this way had the lowest IO compared to other approaches.

This sample would get the last revision to an 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
蓬勃野心 2024-09-13 18:59:29

如果您有一个表,其中仅包含每个父级的最新条目以及父级的 id,那么这会很容易,对吗?

您可以通过将子表连接到其本身来创建这样的表,只获取每个父 ID 的最大日期戳。像这样的东西(您的 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

这会获取子表中对于该父 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

If you had a table which just contained the most recent entry for each parent, and the parent's id, then it would be easy, right?

You can make a table like that by joining the child table on itself, taking only the maximum datestamp for each parent id. Something like this (your SQL dialect may vary):

   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

That gets you all of the rows in the child table for which no higher timestamp exists, for that parent id. You can use that table in a subquery to join to:

   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

or join the parent table directly into it:

   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
能否归途做我良人 2024-09-13 18:59:29

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

Use this query as a basis
Note that the CTE definition is not part of query-So the solution is 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文