内部加入子查询

时间:2013-12-17 00:22:30

标签: sql join

我在一个名为dbo.Task的表中有一个任务列表

在数据库中,每个Task可以在TaskLine表中包含1行或更多行。

TaskLine有一个TaskID,用于将任务线与任务相关联。

TaskLine有一个名为TaskHeadingTypeID

的列

我需要返回所有任务,加入该任务的LAST TaskLine。

在英语中,我需要使用最新的TaskLine标题显示任务。所以,我基本上需要加入TaskLine表,就像这样(这是不正确的,可能效率低下,但希望能显示我想要做的事情)

SELECT *
  FROM @Results r
   INNER JOIN (
      SELECT TOP 1 TaskID, TaskHeadingTypeID FROM dbo.TaskLine
      ORDER BY TaskLineID DESC
    ) tl
      ON tl.TaskID = r.TaskID

然而,问题是,子查询只返回最后一个TaskLine行,这是不正确的。

编辑:

目前,它的工作方式与下面的代码相似,但效率非常低,因为对于每个任务行,它必须运行两个额外的查询。而且它们都在同一张桌子上,只是表中的列略有不同:

(SELECT原因中列的摘录)

 SELECT TaskStatusID,
  TaskStatus,
  (SELECT TOP 1 TaskHeadingTypeID FROM dbo.TaskLine
    WHERE TaskID = r.TaskID
  ORDER BY TaskLineID DESC) AS TaskHeadingID,
  (SELECT TOP 1 LongName FROM dbo.TaskLine tl
    INNER JOIN ref.TaskHeadingType tht
      ON tht.TaskHeadingTypeID = tl.TaskHeadingTypeID
    WHERE TaskID = r.TaskID
  ORDER BY TaskLineID DESC) AS TaskHeading,
  PersonInCareID, 
  ICMSPartyID, 
  CarerID.... FROM... 

编辑:

感谢下面的想法和评论,我最终使用了CTE:

;WITH ValidTaskLines (RowNumber, TaskID, TaskHeadingTypeID, TaskHeadingType)
  AS
    (SELECT 
        ROW_NUMBER()OVER(PARTITION BY tl.TaskID, tl.TaskHeadingTypeID ORDER BY tl.TaskLineID) AS RowNumber,
        tl.TaskID, 
        tl.TaskHeadingTypeID, 
        LongName AS TaskHeadingType
      FROM dbo.TaskLine tl
      INNER JOIN ref.TaskHeadingType tht
      ON tht.TaskHeadingTypeID = tl.TaskHeadingTypeID
    )

  SELECT AssignedByBusinessUserID, 
      BusinessUserID, 
      LoginName, 
      Comments, 
      r.CreateDate, 
      r.CreateUser, 
      r.Deleted, 
      r.Version,
      IcmsBusinessUserID, 
      r.LastUpdateDate, 
      r.LastUpdateUser,
      OverrrideApprovalBusinessUserID, 
      PlacementID, 
      r.TaskID, 
      TaskPriorityTypeID,
      TaskPriorityCode,
      TaskPriorityType,
            TaskStatusID,
      TaskStatus,
      vtl.TaskHeadingTypeID AS TaskHeadingID,
      vtl.TaskHeadingType AS TaskHeading,
      PersonInCareID, 
      ICMSPartyID, 
      CarerID, 
      ICMSCarerEntityID, 
      StartDate, 
      EndDate 
  FROM @Results r
  INNER JOIN ValidTaskLines vtl
    ON vtl.TaskID = r.TaskID
    AND vtl.RowNumber = 1

1 个答案:

答案 0 :(得分:1)

您可以使用ROW_NUMBER()功能:

SELECT *
FROM @Results r
INNER JOIN (SELECT TaskID
                 , TaskHeadingTypeID
                 , ROW_NUMBER()OVER(PARTITION BY TaskID, TaskHeadingTypeID ORDER BY TAskLineID DESC) RN
            FROM dbo.TaskLine
           ) tl
 ON tl.TaskID = r.TaskID
 AND t1.RN = 1

ROW_NUMBER()函数为每一行分配一个数字。 PARTITION BY是可选的,但用于为该组中的每个值开始编号,即:如果您PARTITION BY Some_Date,那么对于每个唯一日期值,编号将从1开始。ORDER BY当然用于定义计数应该如何进行,并且在ROW_NUMBER()函数中是必需的。

您可能需要调整PARTITION BY以适合您的查询,单独运行子查询以了解ROW_NUMBER()的工作原理。