Sql 如果左外联接为真,如何交叉应用
我有一个名为serviceEntry的表和一个名为ServiceEntryPart的表,它与后者有一对多的关系。问题是我只想在左外语句为真时交叉应用 因此,如果我传递一个部件id和一个服务类型id,它应该只在有真正匹配的地方重新运行记录,所发生的是,如果传递一个部件id和一个服务类型id,而该id对于包含该部件的特定记录来说并不存在,我得到的结果不是部件id传递,而是包含该服务类型的记录。如果我通过了零件的正确维修类型,那么我会得到正确的结果Sql 如果左外联接为真,如何交叉应用,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个名为serviceEntry的表和一个名为ServiceEntryPart的表,它与后者有一对多的关系。问题是我只想在左外语句为真时交叉应用 因此,如果我传递一个部件id和一个服务类型id,它应该只在有真正匹配的地方重新运行记录,所发生的是,如果传递一个部件id和一个服务类型id,而该id对于包含该部件的特定记录来说并不存在,我得到的结果不是部件id传递,而是包含该服务类型的记录。如果我通过了零件的正确维修类型,那么我会得到正确的结果 ServiceEntry ID XYZ XYZ S
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
如果没有任何能力来测试这一点,我将提出两种方法,其中一种很少使用,因此您可能希望忽略它 您在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)
或未经测试!您可以使用较少使用的方法,该方法涉及移动ON语句序列。这会改变操作的优先级,在这里我用括号来强调这一点。实际上,执行括号内的联接是为了构造一个派生表,然后该派生表外部联接到se
虽然我相信两者都可以,但第一种选择可能是最容易维护的,因为大多数人更容易掌握
但是,请注意,如果@SelectedPartsIDs不为null,where子句中有一个条件将使所有外部联接无效:
AND (@SelectedPartsIDs IS NULL
OR sep.PartID IN (
SELECT * FROM dbo.SplitInts_RBAR_1(@SelectedPartsIDs, ',')
)
)
在左连接之后要小心内部连接…您将se连接到sep,然后在sep=systemmodule上内部连接systemmodule。se LEFT中的记录连接到sep,但未找到任何内容会导致所有sep字段为空。如果将该空sep值内部联接到另一个表,它将按照标准内部联接规则删除该记录。如果要在结果中删除null sep记录,那么左连接后面的两个内部连接都应该是左连接
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
...