查询具有按日期跟踪的多个记录的表

时间:2011-06-20 18:42:19

标签: sql sql-server sql-server-2005 tsql sql-server-2008

我有多个表7或更多。 有一个主表,所有其他都是子表(FK到主表的主列id)。 所有表都有给定id的多个记录,包括主表,它们按日期(生效日期)进行跟踪。并且最近的日期记录在每个表中被视为活动记录。

是否有一种快速且更好的方式来加入它们并从每个表中返回最近的记录? 现在我从每个表中选择max并加入其中以从不同的表中返回最近的记录。

3 个答案:

答案 0 :(得分:0)

可能为每个表TOP 1生效日期返回ORDER BY的所有表创建一个视图。

然后在主查询中对所有这些视图执行JOIN

答案 1 :(得分:0)

你可以这样写:

select * from masterTable m
cross apply (select top 1 null as dummy from masterTable m2 where m2.id= m.id order by m2.effectDate desc) mm1
cross apply (select top 1 * from detailTable1 d1 where d1.masterId = m.id order by d1.effectDate desc) dd1
cross apply (select top 1 * from detailTable2 d2 where d2.masterId = m.id order by d2.effectDate desc) dd2
cross apply (select top 1 * from detailTable2 d2 where d3.masterId = m.id order by d3.effectDate desc) dd2

我没有你的桌子,所以我无法测试,希望这有帮助。

答案 2 :(得分:0)

因为你有一个inkex(id,effdt)我认为你已经描述了查询模式的最有效方法。至少,你描述的方法是我这样做的方式......

SELECT
  *
FROM
  master
INNER JOIN
  child1
    ON child1.id = master.id
INNER JOIN
  child2
    ON child2.id = master.id
WHERE
      master.effdt = (SELECT TOP 1 effdt FROM master AS lookup WHERE id = master.id)
  AND child1.effdt = (SELECT TOP 1 effdt FROM child1 AS lookup WHERE id = child1.id)
  AND child2.effdt = (SELECT TOP 1 effdt FROM child2 AS lookup WHERE id = child2.id)

解析不同的子查询(我使用TOP 1,MAX()也可以工作)然后成为索引查找。

有一种替代方案,但我不记得有任何显着的性能优势......

SELECT
  *
FROM
  (SELECT ROW_NUMBER() OVER (PARTITION BY id ORDER BY effdt), * FROM master) AS master
INNER JOIN
  (SELECT ROW_NUMBER() OVER (PARTITION BY id ORDER BY effdt), * FROM child1) AS child1
    ON child1.id = master.id
INNER JOIN
  (SELECT ROW_NUMBER() OVER (PARTITION BY id ORDER BY effdt), * FROM child2) AS child2
    ON child2.id = master.id
WHERE
      master.seq_id = 1
  AND child1.seq_id = 1
  AND child2.seq_id = 1

此外,还有Maziar提到的CROSS APPLY选项...

SELECT
  *
FROM
  master
CROSS APPLY
  (SELECT TOP 1 * FROM child1 WHERE id = master.id ORDER BY effdt DESC) AS child1
CROSS APPLY
  (SELECT TOP 1 * FROM child2 WHERE id = master.id ORDER BY effdt DESC) AS child2
WHERE
  master.effdt = (SELECT TOP 1 effdt FROM master AS lookup WHERE id = master.id)