如果左外连接为真,如何交叉应用

时间:2014-08-28 22:51:55

标签: sql sql-server tsql

我有一个名为serviceEntry的表和一个名为ServiceEntryPart的表,它与后者具有一对多的关系。问题是我只想在左外部语句为真时交叉应用。

因此,如果我传递一个部分ID和一个服务类型id,它应该只返回存在真匹配的记录,如果传递一个partid和一个服务类型id,那么该特定记录是不存在的部分,我得到的结果没有部分ID传递,但包含服务类型的记录。如果我为部件传递了正确的服务类型,那么我会得到正确的结果。

ServiceEntry
ID
XYZ
XYZ

ServiceEntrPart    Sample Data
ID                 1
ServiceEntrID      10
ServiceEntryPart   1,2,3

   IF (@SelectedSystemIDs = '')                        
      begin        
          SET @SelectedSystemIDs = NULL         
      END         

IF (@SelectedPartsIDs = '')                        
  begin        
      SET @SelectedPartsIDs = NULL         
  END         

IF(@UserRoleID = 1)    
 BEGIN     
  SET @PlatformID = 1     
  END  

IF(@UserRoleID = 2)  
BEGIN  
SET @PlatformID = 2  
END  

IF (@UserRoleID = 3)    
BEGIN    
SET @PlatformID = 12    
END   

IF(@UserRoleID = 4)
BEGIN 
SET @PlatformID = 3
END

IF(@UserRoleID = 5)
BEGIN 
SET @PlatformID = 4
END

IF(@UserRoleID = 6)
BEGIN 
SET @PlatformID = NULL
END
--SET @Reconciled = 'R'

IF(@Reconciled='R')                            
 set @ReconciledValue=1                            
ELSE IF(@Reconciled='N')                            
 set @ReconciledValue=0   
ELSE IF(@Reconciled = 'A')
 set @ReconciledValue = null                         

--SET @ServiceTypes = '9'

IF @ServiceTypes = ''                        
  SET @ServiceTypes = NULL                          

IF @ServiceTypes IS NULL                   
  SET @flag = 2                  
 ELSE                    
 set @flag = 100                  

 IF (@SelectedSystemIDs = '')                    
    begin    
      SET @SelectedSystemIDs = NULL     
    END  

  Select     
   se.ID as ServiceEntryID,    
   se.ServiceDateTime,
   se.ReasonForFailure,
   se.ActionTaken,
   se.VerificationPerformed,
   se.TSBNumber,
   se.ISANumber,
   (SELECT     
  CAST(ID AS varchar(6)) + ' ~ ' + PartDescriptionWithParent FROM [RunLogTest].[dbo].[Part]       
    where id= sep.PartID) as PartDescriptionWithParent ,       
   (SELECT SystemFullName from System WHERE ID=se.SystemID
   )as SystemName,    
   se.Reconciled,
   se.CreatedDate,
   se.ClosedDate,
   se.UpdatedDate,
   se.ServiceHours,
   se.ServiceMinutes     
   FROM     
   [ServiceEntry] se left outer JOIN  
   ServiceEntryPart sep  ON se.ID = sep.ServiceEntryID   
   INNER JOIN SystemModule ON sep.SystemModuleID = SystemModule.ID  
   INNER JOIN System ON SystemModule.SystemID = System.ID 
   CROSS apply
   dbo.SplitStrings_Moden(sep.ServiceTypeIDs, N',') M2
   JOIN  dbo.SplitStrings_Moden(@ServiceTypes, N',') P ON (M2.Item = P.Item   or @ServiceTypes IS NULL)
   where se.ID=ServiceEntryID AND (se.Active = 1)
   AND (@ReconciledValue IS NULL OR se.Reconciled = @ReconciledValue)
   AND (@SelectedSystemIDs IS NULL OR  se.SystemID IN(select  * from dbo.SplitInts_RBAR_1(@SelectedSystemIDs, ',')))
   AND (@SelectedPartsIDs IS NULL or sep.PartID IN(select * from dbo.SplitInts_RBAR_1(@SelectedPartsIDs, ',')))
   AND (se.ServiceDateTime between @StartDate and @EndDate)
   AND ((@PlatformID IS NULL) OR  (System.PlatformID = @PlatformID) OR (@PlatformID = 12 AND System.PlatformID <= 2))  
   order by se.CreatedDate desc

2 个答案:

答案 0 :(得分:0)

如果没有任何测试能力,我会提出两种方法,一种很少使用,所以你可能想忽略它。

您在sesep之间形成外部联接,因此要保留外部联接关系,您需要确保加入sep的任何内容也允许外部联接。这将需要更多的左连接和外部应用,如下所示:

-- common approach
FROM [ServiceEntry] se
      LEFT OUTER JOIN ServiceEntryPart sep
                  ON se.ID = sep.ServiceEntryID
      LEFT OUTER JOIN JOIN SystemModule
                  ON sep.SystemModuleID = SystemModule.ID
      LEFT OUTER JOIN JOIN System
                  ON SystemModule.SystemID = System.ID
      OUTER APPLY dbo.SplitStrings_Moden(sep.ServiceTypeIDs, N',') M2
      LEFT OUTER JOIN dbo.SplitStrings_Moden(@ServiceTypes, N',') P
                  ON (M2.Item = P.Item OR @ServiceTypes IS NULL)

OR(未经测试!)您可以使用较少使用的方法,该方法涉及移动ON语句的序列。这样做会改变操作的优先级,这里我用括号来突出显示这一点。实际上,括号内的连接被执行以构造derived table THEN,其外部连接到se

-- much less common           
FROM [ServiceEntry] se
      LEFT OUTER JOIN ServiceEntryPart sep
              (
                  INNER JOIN SystemModule
                              ON sep.SystemModuleID = SystemModule.ID
                  INNER JOIN System
                              ON SystemModule.SystemID = System.ID
                  CROSS APPLY dbo.SplitStrings_Moden(sep.ServiceTypeIDs, N',') M2
                  JOIN dbo.SplitStrings_Moden(@ServiceTypes, N',') P
                              ON (M2.Item = P.Item OR @ServiceTypes IS NULL)
              )
              ON se.ID = sep.ServiceEntryID

虽然我相信其中任何一种都可行,但第一种选择可能是最易于维护的,因为大多数人都更容易掌握。

但是,请注意where子句中有一个条件会使所有外连接无效 IF @SelectedPartsIDs不为null:

  AND (@SelectedPartsIDs IS NULL
        OR sep.PartID IN (
              SELECT * FROM dbo.SplitInts_RBAR_1(@SelectedPartsIDs, ',')
                         )
      )

答案 1 :(得分:0)

...
FROM dbo.[ServiceEntry] se
    left outer JOIN (
        dbo.ServiceEntryPart sep
        CROSS apply dbo.SplitStrings_Moden(sep.ServiceTypeIDs, N',') M2
    ) ON se.ID = sep.ServiceEntryID
...