抱歉,如果没有某种子查询,就没有真正的方法可以做到这一点。你写的查询很好。在我看来,完成您正在寻找的最佳语法是:
SELECT
T.ID,
HT.*
FROM
dbo.Test T
OUTER APPLY (
SELECT TOP 1 *
FROM dbo.TestHistory HT
WHERE T.ID = HT.TestID
ORDER BY HT.ID DESC
) HT
;
在 SQL Fiddle 中自己尝试一下。
如果您想限制它以便只显示Test
具有匹配TestHistory
行的那些行,则使用CROSS APPLY
而不是OUTER APPLY
.
TestHistory
此外,这样的查询是可能的并且可能更容易理解,但很可能不会执行得那么好,而且它要求每行至少有Test
一行。
SELECT
T.ID,
HT.*
FROM
dbo.Test T
INNER JOIN dbo.TestHistory HT
ON T.ID = HT.TestID
WHERE
HT.ID = (
SELECT Max(HT2.ID)
FROM dbo.TestHistory HT2
WHERE T.ID = HT2.TestID
)
;
您也可以使用一个Row_Number()
解决方案,尽管我倾向于不使用它,因为它的性能通常不如CROSS APPLY
with TOP
,当它可用时。
SELECT
T.ID,
HT.TestID,
HT.Price
FROM
dbo.Test T
LEFT JOIN (
SELECT
Selector = Row_Number() OVER (
PARTITION BY HT.TestID ORDER BY HT.ID DESC
),
*
FROM dbo.TestHistory HT
) HT
ON T.ID = HT.TestID
AND HT.Selector = 1
;
在 SQL Fiddle 中自己尝试一下。
找出TOP 1
该Row_Number()
解决方案是否性能更好的唯一方法是使用大量具有适当代表性的数据尝试数据库中的每一个。如果您的历史条目非常少而主要条目非常多,则使用Row_Number()
. 但是,如果每个主要条目都有许多历史条目,则该TOP
方法可能会执行得最好。
表上的索引也可以产生巨大的影响。确保您有合理的索引,允许正确的表访问(例如,表上的聚集索引TestHistory
应该是 on TestID, ID
,即使 PK 是 on ID
')。如果您每次都查询整个表,索引可能没那么重要,但是当您有限制Test
行集的条件时,索引将变得非常重要。