【问题标题】:Simple Table Join with access to joined table columns可以访问连接表列的简单表连接
【发布时间】:2012-04-24 09:57:52
【问题描述】:

我有一个简单的项目表。称它们为“零件”。

每个部分在单独的表中可以有零个或多个相关条目,称它们为“子部分”。 正如您可能期望的那样,表格的简单视图是:

Parts
-----
PartID int (PK)
PartName varchar

SubParts
--------
SubPartID int (PK)
PartID int (FK_Parts)
SubPartName varchar
SubPartAdded datetime

我想返回主表中的所有部分,但也可以访问 LATEST(按 SubPartAdded DESC 排序)相关的 SubPart(如果存在)。

我的困惑是 subparts 表中有 1M+ 条目(对于许多不同的部分),我只需要当前部分的最新条目(如果存在)。

之前我写了一个语句,在 Parts 表和相关子部件的派生表之间执行左连接(有效),但派生表 似乎返回 subparts 表中的所有行,导致性能受到打击。我基本上需要在派生的 select 语句中执行 TOP 1 并按 DESC 排序,以按 PartID(和其他一些列)预过滤子部分。但是,由于我似乎无法在派生的 select 语句中引用 Parts 表(外部)列,因此我无法向派生表添加 WHERE 子句。

我也试过下面的sn-p,它确实执行了,但没有返回任何相关记录:

    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

我想“TOP 1”语句正在对整个 SubParts 表执行,然后被“ON”语句过滤(?)

最终我需要在主存储过程中的多个位置使用 Subparts 表中的一些列,所以我不只是想要一个相关的子查询,因为这需要被调用多次。

(此过程将在每次执行时返回多个部分。即,该过程不会被单个 PartID 过滤)

我希望这很清楚? 听起来它应该有一个非常简单的解决方案,但我现在很难过! (需要兼容SQL Server 2K及以上版本)

问候 尼克

【问题讨论】:

    标签: sql sql-server sql-server-2000


    【解决方案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。

    【讨论】:

      【解决方案2】:

      您需要一个派生表来提取最后的子部分。然后您可以通过 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
      

      【讨论】:

      • 您的第一个查询需要 GROUP BY,而不是 MaxSP 子查询中的 ORDER BY。即使进行了此更正,它也会返回所有子部分。您需要一个 where 子句来声明类似 WHERE MaxSp.PartID IS NOT NULL OR sp.PartID IS NULL 的内容,这将删除不是最新的子部分,同时仍然允许没有子部分的部分。
      • @GarethD 我搞砸了编辑。它应该在join子句中表示。
      猜你喜欢
      • 1970-01-01
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 2021-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多