我有一个名为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
答案 0 :(得分:0)
如果没有任何测试能力,我会提出两种方法,一种很少使用,所以你可能想忽略它。
您在se
和sep
之间形成外部联接,因此要保留外部联接关系,您需要确保加入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
...