简体   繁体   English

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

[英]how to cross apply if left outer join is true

I have a table called serviceEntry and table Called ServiceEntryPart which has a one to many relationship with the later. 我有一个名为serviceEntry的表和一个名为ServiceEntryPart的表,该表与后者具有一对多的关系。 The problem is I want to cross apply only if the left outer statement is true. 问题是我只想在左外部声明为true时交叉应用。

So if I pass a part id and a service type id, it should only retun records where there is a true match, whats happeneing is if pass a partid and a service type id which did not exist for the specific record which has the part, I am getting results which did not have the part id passes but the records which contained the service type. 因此,如果我传递部件ID和服务类型ID,则它仅应重新调整记录中存在真正匹配项的记录,发生的情况是,传递具有部件的特定记录不存在的部件ID和服务类型ID,我得到的结果没有部件ID通过,但是包含服务类型的记录。 If I pass the correct service type for the part then I get correct results. 如果我为零件传递了正确的服务类型,那么我会得到正确的结果。

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

Without any ability to test this I would propose 2 methods, one is rarely used so you might want to ignore it. 没有任何能力对此进行测试,我会提出2种方法,一种方法很少使用,因此您可能希望忽略它。

You form an outer join between se and sep , so to retain that outer join relationship you need to ensure anything joining to sep also permits the outer join. 您在sesep之间形成一个外部sep ,因此要保持该外部联接关系,您需要确保对sep任何sep也允许该外部联接。 That would require more left joins, and an outer apply, like this: 这将需要更多的左连接和外部应用,如下所示:

-- 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 (untested!) you can use a less used approach which involves moving the sequence of ON statements. 或(未测试!),您可以使用较少使用的方法,该方法涉及移动ON语句的序列。 What this does is changes the precedence of operation, and here I have shown brackets to highlight this. 这样做是改变操作的优先级,在这里我显示了括号来突出显示此操作。 In effect the joins inside the brackets are performed to construct a derived table THEN that is outer joined to se 实际上,将执行方括号内的联接以构造derived table THEN,该derived table将外部联接到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

Whilst I believe either will work the first option is probably the most maintainable as it is easier for most folks to grasp. 虽然我相信任何一种方法都可以工作,但第一种选择可能是最可维护的,因为大多数人都更容易掌握。

However, do note that there is a condition in your where clause that would invalidate all outer joins IF @SelectedPartsIDs is not null: 但是,请注意, 如果 @SelectedPartsIDs不为null,则where子句中存在使所有外部联接无效的条件:

  AND (@SelectedPartsIDs IS NULL
        OR sep.PartID IN (
              SELECT * FROM dbo.SplitInts_RBAR_1(@SelectedPartsIDs, ',')
                         )
      )
...
FROM dbo.[ServiceEntry] se
    left outer JOIN (
        dbo.ServiceEntryPart sep
        CROSS apply dbo.SplitStrings_Moden(sep.ServiceTypeIDs, N',') M2
    ) ON se.ID = sep.ServiceEntryID
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM