0

我有如下所述的三个表:

dbo.ServiceEntry
ID  RunLogEntry  Reconciled
1    0            1
2    4            1
3    5            1

dbo.ServiceEntryPart
ID  ServiceEntryID  PartId     ServiceEntryTypeID
1    1                3          1
2    2                4          2
3    2                4          1,2

dbo.Part
ID  Desc     Active (bitfield)
3   xyz        1
4   abc        1

查询如下:

SELECT * 
  FROM ServiceEntry AS S 

 WHERE (S.RunLogEntryID is not null) AND (S.Reconciled=@ReconciledValue) 
   AND EXISTS (SELECT ServiceEntryID 
                 FROM ServiceEntryPart   SEP  
                 JOIN Part on SEP.PartID = Part.ID    
                WHERE ((@ActivePart = 0 AND Part.Active is not null) 
                    OR (@ActivePart = 1 and Part.Active = 0))      
                  AND (@ServiceTypes is null 
                    OR CHARINDEX(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+@ServiceTypes+',') > 0))
    OR (NOT EXISTS (SELECT ServiceEntryID 
                      FROM ServiceEntryPart   SEP  
                      JOIN Part on SEP.PartID = Part.ID))

服务条目有一些包含runlogentry id 为0 的记录。如果服务条目表中的runlogentryid 值为0,则该服务条目将没有服务条目部分记录。这就是为什么我将它们分成两部分,正如您从查询中注意到的那样,例如存在和不存在。exists 语句处理所有具有服务条目部分的服务条目,对于这些条目,过滤器将适用。如果过滤器有值,则不需要不存在块,因为过滤器 servicetypeids 和 activepart 仅用于具有服务条目部分的记录。因此,换句话说,如果没有传递参数,则第一个存在块获取具有服务部分的服务条目,不存在获取具有 0 或非空的 runlogentry id 的服务条目。这很好用。问题是当参数通过时,我需要排除没有服务条目部分的服务条目,当它们存在时,我没有得到正确的结果。我希望我在解释问题方面做得很好。请帮忙

4

3 回答 3

0

这可能不是您想要的,老实说,查询似乎无处不在。

您可能正在寻找像“(@ActivePart 为空或@ActivePart = Part.Active)”这样的活动部件过滤器。您的存在由内部连接隐式处理。我认为与您要查找的内容接近的查询如下。

select *
FROM ServiceEntry AS S
INNER JOIN ServiceEntryPart AS SEP ON SEP.ServiceEntryID = S.ServiceEntryID
INNER JOIN Part AS P ON P.PartID = SEP.PartID
WHERE S.RunLogEntryID is not null
    and S.Reconciled = @ReconciledValue
    and (@ActivePart is null or @ActivePart = Part.Active)
    and (@ServiceTypes is null or charindex(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+@ServiceTypes+',') > 0
于 2012-07-25T04:31:13.503 回答
0

我不能确定,因为我没有您列的业务定义,但我怀疑您处理 Part.Active 的条件是错误的。我希望这些值是 0 或 1,而不是 NULL 或 0。所以我应该认为当参数为 NULL 或参数与列匹配时,测试应该返回 TRUE。

您的 CHARINDEX 函数的参数颠倒了。

您需要额外的括号来获得正确的操作顺序,并且您的 OR NOT EXISTS 子句需要额外的条件才能使其仅在参数为 NULL 时才为真。

我相信以下内容更接近您正在寻找的内容。但我担心 ServiceTypes 测试。只有当参数包含单个 ServiceTypeID 时,它才会可靠地工作。如果它包含多个 ID,则可能无法正常工作。例如,我认为“1,3”的参数值应该匹配“1,2,3”的列表,但它不会。

SELECT *
  FROM ServiceEntry AS S
 WHERE (S.RunLogEntryID IS NOT NULL)
   AND (S.Reconciled=@ReconciledValue)
   AND( EXISTS(
          SELECT ServiceEntryID
            FROM ServiceEntryPart SEP
            JOIN Part ON SEP.PartID = Part.ID
           WHERE( @ActivePart IS NULL
                  OR @ActivePart = Part.Active
                )
             AND ( @ServiceTypes IS NULL
                   OR CHARINDEX( ','+@ServiceTypes+',',
                                 ','+cast(SEP.ServiceTypeIDs as varchar(255))+','
                               ) > 0
                 )
        )
        OR( @ActivePart IS NULL
            AND @ServiceTypes IS NULL
            AND NOT EXISTS( SELECT ServiceEntryID
                              FROM ServiceEntryPart SEP
                              JOIN Part on SEP.PartID = Part.ID
                          )
          )
      )
于 2012-07-25T11:28:03.927 回答
0

在不尝试理解 SQL 的其余部分的情况下,如果您只想在参数为 null 时避免使用 NOT EXISTS 子句,则可以执行类似的操作。

SELECT * 
  FROM ServiceEntry AS S 
  JOIN     
 WHERE (S.RunLogEntryID is not null) AND (S.Reconciled=@ReconciledValue) 
   AND EXISTS (SELECT ServiceEntryID 
                 FROM ServiceEntryPart   SEP  
                 JOIN Part on SEP.PartID = Part.ID    
                WHERE ((@ActivePart = 0 AND Part.Active is not null) 
                    OR (@ActivePart = 1 and Part.Active = 0))      
                  AND (@ServiceTypes is null 
                    OR CHARINDEX(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+@ServiceTypes+',') > 0))
    OR (@ReconciledValue is null and @ActivePart is null and @ServiceTypes is null
        and (NOT EXISTS (SELECT ServiceEntryID 
                      FROM ServiceEntryPart   SEP  
                      JOIN Part on SEP.PartID = Part.ID)))
于 2012-07-25T04:30:22.453 回答