很抱歉,如果没有某种子查询,就没有真正的方法可以做到这一点。你写的查询很好。在我看来,完成您正在寻找的最佳语法是这样的:
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
;
Try this out yourself in a SQL Fiddle.
如果您想限制它,只显示具有匹配 TestHistory 行的那些 Test 行,则使用 CROSS APPLY 而不是 OUTER APPLY。
此外,这样的查询是可能的并且可能更容易理解,但很可能不会执行得那么好,而且它要求每个 Test 行至少有一个 TestHistory 行。
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 和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
;
Try this out yourself in a SQL Fiddle.
确定TOP 1 或Row_Number() 解决方案性能是否更好的唯一方法是使用大量具有适当代表性的数据尝试数据库中的每一个。如果您的历史记录条目非常少而主要条目非常多,您可能使用Row_Number() 获得更好的结果。但如果每个主条目都有很多历史条目,TOP 方法可能会执行得最好。
表上的索引也可以产生巨大的影响。确保您拥有允许正确表访问的合理索引(例如,表TestHistory 上的聚集索引应该在TestID, ID 上,即使PK 在ID' 上也是如此)。如果您每次都查询整个表,索引可能没那么重要,但是当您有条件限制Test 行集时,索引将变得非常重要。