[英]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. 您在se
和sep
之间形成一个外部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.