如果两列值不相同,则过滤行 - sql server

时间:2013-12-11 17:27:18

标签: sql sql-server-2008

我需要在OwningOfficeID和ScopeOfficeID不相同的行上应用日期过滤器。

这是主要查询;

SELECT distinct v.VisitID, a.OfficeID AS OwningOfficeID, 
       scp.OfficeID AS ScopeOfficeID, V.VisitDate, 
       a.staffID as OwningStaff ,scp.StaffID as OwningScope
 FROM Visits v 
    INNER JOIN VisitDocs  vdoc ON vdoc.VisitID = v.VisitID 
    INNER JOIN InspectionScope scp ON scp.ScopeID = v.ScopeID 
    INNER JOIN Assignments a ON a.AssignmentID = scp.AssignmentID 
    INNER JOIN Staff s ON s.StaffID = a.StaffID
 WHERE 
  v.VisitType = 1  AND
 --'SCOPE OWNER AND LOOK FOR INSPECTION REPORT BUT NOT FOR COORD/FINAL REPORT.
     (scp.StaffID = 141
        AND EXISTS(SELECT *           
                     FROM VisitDocs d          
                    WHERE d.VisitID = v.VisitID          
                      AND d.docType = 13)          
        AND NOT EXISTS(SELECT * 
                         FROM VisitDocs d  
                        WHERE d.VisitID = v.VisitID  AND d.docType IN (1,2))
     )
     OR 
--'ASSIGNMENT OWNER AND NOT SCOPE OWNER AND LOOK FOR COORDINATOR REPORT. 
(a.StaffID = 141 AND scp.StaffID != 141
 AND EXISTS(SELECT *           
                 FROM VisitDocs d          
                 WHERE d.VisitID = v.VisitID          
                 AND d.docType = 2)          
 AND NOT EXISTS(SELECT * FROM VisitDocs d  
                 WHERE d.VisitID = v.VisitID  AND d.docType IN (1))
 )

结果集

enter image description here

以下条件可以应用于外部选择查询以实现结果。

(OwningOfficeID<> ScopeOfficeID和VisitDate> ='01/11/2012'或OwningOfficeID = ScopeOfficeID)

无论如何都要在一个select语句中执行此操作吗?

1 个答案:

答案 0 :(得分:0)

我不确定你的一个选择语句是什么意思,但我认为你真正想知道的是如何进行这种查询以便它快速运行,很容易看出它是正确的,易于维护。 / p>

以下是如何做到这一点;使用CTE。 (如果您不知道CTE是什么,请阅读它们然后再回到这里 - 它们会记录在Microsoft的网站上。)

CTE可以比子查询更快更清晰。让我告诉你如何,采用上面的代码并重新分解我得到的CTE:

WITH DocTypes AS 
(
   SELECT VisitID, docType
   FROM VisitDocs
), DocType13 AS
(
   SELECT VisitID
   FROM DocTypes 
   WHERE docType = 13
), DocType1and2 AS
(
   SELECT VisitID
   FROM DocTypes 
   WHERE docType IN (1,2)
), DocType1 AS
(
   SELECT VisitID
   FROM DocTypes1and2 
   WHERE docType = 1
), DocType2 AS
(
   SELECT VisitID
   FROM DocTypes1and2 
   WHERE docType = 2
), Base AS
(
  SELECT distinct v.VisitID, a.OfficeID AS OwningOfficeID, 
         scp.OfficeID AS ScopeOfficeID, V.VisitDate, 
         a.staffID as OwningStaff ,scp.StaffID as OwningScope
   FROM Visits v 
      INNER JOIN VisitDocs  vdoc ON vdoc.VisitID = v.VisitID 
      INNER JOIN InspectionScope scp ON scp.ScopeID = v.ScopeID 
      INNER JOIN Assignments a ON a.AssignmentID = scp.AssignmentID 
      INNER JOIN Staff s ON s.StaffID = a.StaffID
   WHERE 
    v.VisitType = 1  AND
   --'SCOPE OWNER AND LOOK FOR INSPECTION REPORT BUT NOT FOR COORD/FINAL REPORT.
       (scp.StaffID = 141
          AND EXISTS(SELECT * FROM DocType13 d WHERE d.VisitID = v.VisitID)          
          AND NOT EXISTS(SELECT * FROM DocType1and2 d WHERE d.VisitID = v.VisitID)
       )
       OR 
  --'ASSIGNMENT OWNER AND NOT SCOPE OWNER AND LOOK FOR COORDINATOR REPORT. 
  (a.StaffID = 141 AND scp.StaffID != 141
    AND EXISTS(SELECT * FROM DocType2 d WHERE d.VisitID = v.VisitID)          
    AND NOT EXISTS(SELECT * FROM DocType1 d WHERE d.VisitID = v.VisitID)
  )
)
SELECT *
FROM Base
WHERE (OwningOfficeID <> ScopeOfficeID 
      AND VisitDate >='01/11/2012'( 
      OR OwningOfficeID = ScopeOfficeID 

应该清楚为什么这更好,但如果不是短暂的:

  • 您在开头看到的所有选择与原始查询中的选择完全相同,但由于它们在优化程序更容易的时间之前被分解,因此它将比在子查询时更好 - - 在某些情况下我看到了很大的变化,但无论如何,优化器现在可以选择更好地进行内存缓存等。

  • 测试更清晰,更容易。如果您对查询有疑问,可以轻松测试,注释掉主要选择并选择其中一个子查询,这是您所期望的吗?这些子查询很简单,但它们可能会变得复杂,这使得它更容易。

  • 您说过想要对此查询应用一些逻辑。我已将它添加到CTE中,因为您可以看到它使这种复杂的“分层”变得简单。