我需要在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))
)
结果集
以下条件可以应用于外部选择查询以实现结果。
(OwningOfficeID<> ScopeOfficeID和VisitDate> ='01/11/2012'或OwningOfficeID = ScopeOfficeID)
无论如何都要在一个select语句中执行此操作吗?
答案 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中,因为您可以看到它使这种复杂的“分层”变得简单。