我有一个简单的项目表。称他们为“零件”。
每个部分在单独的表中可以有零个或多个相关条目,称之为“子部件”。 正如您可能期望的那样,表格的简单视图是:
Parts
-----
PartID int (PK)
PartName varchar
SubParts
--------
SubPartID int (PK)
PartID int (FK_Parts)
SubPartName varchar
SubPartAdded datetime
我想从主表返回所有部分,但也可以访问LATEST(由SubPartAdded DESC订购)相关的SubPart(如果存在)。
我的困惑是,子部分表中有一些1M +条目(对于许多不同的部分),我只需要当前部分的最新部分(如果存在)。
之前我写了一个声明,它在Parts表和相关子部分的派生表之间执行左连接(可以工作),但派生表似乎返回子部分表中的所有行,导致性能打击。我基本上需要在派生的select语句中通过DESC执行TOP 1和命令,以通过PartID(以及其他一些列)预过滤子部分。但是,由于我似乎无法引用派生的select语句中的Parts表(外部)列,所以我无法在派生表中添加WHERE子句。
我还尝试了以下代码片段,它执行但不返回任何相关记录:
SELECT p.PartName, sp.SubPartName, sp.SubPartAdded
FROM Parts p
LEFT JOIN (SELECT TOP 1 SubPartID, SubpartAdded, PartID FROM SubParts ORDER BY SubPartAdded) AS sp
ON sp.PartID = p.PartID
我想在通过“ON”语句过滤之前,“TOP 1”语句正在对整个SubParts表执行(?)
最终我需要在主存储过程中的多个位置使用Subparts表中的一些列,所以我不想只需要一个相关的子查询,因为这需要多次调用。
(此proc将在每次执行时返回多个部分。即proc不会被单个PartID过滤掉)
我希望这很清楚吗? 听起来它应该有一个非常简单的解决方案,但我现在很难过! (需要与SQL Server 2K及更高版本兼容)
此致 尼克
答案 0 :(得分:1)
以下内容应该可以回溯到SQL Server 2000。
SELECT PartName, SubPartName, SubPartAdded
FROM Parts
LEFT JOIN
( SELECT SubParts.PartID, SubParts.SubPartName SubParts.SubPartAdded
FROM SubParts
INNER JOIN
( SELECT PartID, MAX(SubPartAdded) [SubPartAdded]
FROM SubParts
GROUP BY PartID
) MaxSubPart
ON MaxSubPart.PartID = SubParts.PartID
AND MaxSubPart.SubPartAdded = SubParts.SubPartAdded
) Subpart
ON SubPart.PartID = Parts.PartID
在更高版本(OUTER APPLY或Window函数)中有更高效和更有效的方法,但我不确定有多少方法可以向后兼容SQL Server 2000.
答案 1 :(得分:0)
您需要派生表来提取最后的子部分。然后,您可以通过id和SubPartAdded列过滤将其连接到派生表的子部分:
SELECT p.PartName, sp.SubPartName, sp.SubPartAdded
FROM Parts p
LEFT JOIN SubParts sp
ON p.PartID = sp.PartID
LEFT JOIN
(
SELECT PartID, max (SubPartAdded) MaxSubPartAdded
FROM SubParts
GROUP BY PartID
) AS MaxSP
ON sp.PartID = MaxSP.PartID
AND sp.SubPartAdded = MaxSP.MaxSubPartAdded
如果是Sql Server 2005或更新版本:
SELECT p.PartName, sp.SubPartName, sp.SubPartAdded
FROM Parts p
OUTER APPLY
(
select top 1
SubPartName, SubPartAdded
from SubParts
where SubParts.PartID = p.PartID
order by SubPartAdded desc
) sp