2

我有一些 SQL,要添加这个问题中的所有语句太多了,我正在努力改进以消除系统减速。

在部分 PL/SQL 中有一个AND Exists子句,其中包含一个AND Not Exists子句。

这两个子句都包含Case语句。在 case 语句的End部分之后,有一个IS NOT NULLIS NULL语句。使用 PL/SQL 多年,这是我第一次看到这种语法,我坦率地承认不理解它。整个AND Exists子句如下所示,非常感谢您的帮助。

AND EXISTS  (
  SELECT Distinct PROJECTID
  From Milestone_History MH, 
       Project_Milestone PM
  Where MH.MilestoneId = PM.ID
    AND MH.Projectid = PR.ID
    AND ((UPPER(PM.Description) = 'FINAL BUILD INVOICE INSTRUCTIONS ISSUED') OR
         (UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED') OR
         (UPPER(PM.Description) = 'PROJECT COMPLETE'))
     AND (case when UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED' then
                  Actual
                End IS NOT NULL 

                AND 
                  case
                    when UPPER(PM.Description) = 'PROJECT COMPLETE' then
                      MH.Actual
                  end IS NULL)
           AND NOT EXISTS
         (SELECT Distinct MH2.ProjectID
          From Milestone_History MH2, Project_Milestone PM2
          Where MH2.MilestoneId = PM2.ID
            And MH2.ProjectID = MH.ProjectID
            AND case
                    when UPPER(PM2.Description) = 'PROJECT COMPLETE' then  -
                          MH2.Actual
                    end IS NOT NULL))
4

2 回答 2

3

将 theCASE...END视为单个表达式。您可以使用括号来更好地理解:

(case when UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED' 
    then Actual
 End) IS NOT NULL

此特定表达式是NOT NULL当且仅当CASE找到匹配项Actual且不为空时。

这可以重写为:

(UPPER(pm.description) = 'FEASIBILITY STUDY REQUIRED'
AND actual IS NOT NULL)

下面的语句可以改写为:

(UPPER(PM.Description) != 'PROJECT COMPLETE'
 OR PM.Description IS NULL
 OR actual IS NULL)

这两个陈述显然是重叠的:Descrition只能有一个值。当我们合并它们时,剩下的不多了:

(SELECT Distinct PROJECTID
   From Milestone_History MH, 
        Project_Milestone PM
  Where MH.MilestoneId = PM.ID
    AND MH.Projectid = PR.ID
    AND UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED'
    AND actual IS NOT NULL
    AND NOT EXISTS
         (SELECT Distinct MH2.ProjectID
            From Milestone_History MH2, Project_Milestone PM2
           Where MH2.MilestoneId = PM2.ID
             And MH2.ProjectID = MH.ProjectID
             AND PM2.Description = 'PROJECT COMPLETE'
             AND MH2.Actual IS NOT NULL)
)

CASE我认为当只有一个案例时使用它有点误导。

要么作者被错误地告知了其行为,CASE要么这是沿途更新的残留代码而没有被清理。

于 2013-05-14T16:32:39.447 回答
2

前两个条件:

 Where MH.MilestoneId = PM.ID
   AND MH.Projectid = PR.ID

- 连接子查询中的两个表,并将子查询连接到主查询。

接下来的三个条件:

AND (UPPER(PM.Description) = 'FINAL BUILD INVOICE INSTRUCTIONS ISSUED' OR
     UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED' OR
     UPPER(PM.Description) = 'PROJECT COMPLETE')

- 确保这Description是三个值之一。

但是下一个条件:

AND case when UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED' 
         then Actual End IS NOT NULL 

- 虽然本身可以,但与前面三个条件中的两个相矛盾。写成的表达式CASE WHEN condition THEN value END IS NOT NULL本质上是说必须condition真(否则 CASE 子句的计算结果为 NULL)并且该值不能为 NULL;它可以重写为:

AND UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED' 
AND Actual IS NOT NULL 

- 这更清晰,更简洁(并排除了前一个括号子句中的三个条件中的两个)。

下一个条件:

AND case when UPPER(PM.Description) = 'PROJECT COMPLETE' 
         then MH.Actual end IS NULL

- 尽管(再次)本身还可以,但由于先前的条件,本质上是多余的;它可以重写为:

AND (UPPER(PM.Description) <> 'PROJECT COMPLETE' OR MH.Actual IS NULL)

- 再次,更清晰,更简洁。这也是不必要的,因为前面的条件UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED'确保它UPPER(PM.Description) <> 'PROJECT COMPLETE'始终为真。

NOT EXISTS子句可以作为单独的子句包含在子句之外的主查询的末尾EXISTS,只需更改And MH2.ProjectID = MH.ProjectID为 - 但是,查询应该在子句内部的子句中And MH2.ProjectID = PR.ProjectID执行得更快一些,因为只有在其余的情况下才会评估它的条款是真的。NOT EXISTSEXISTSEXISTS

与前面的 IS NOT NULL 条件一样,表达式:

  AND case when UPPER(PM2.Description) = 'PROJECT COMPLETE' 
           then MH2.Actual end IS NOT NULL

- 可以改写为:

  AND UPPER(PM2.Description) = 'PROJECT COMPLETE' 
  AND MH2.Actual IS NOT NULL

所以整个子句可以改写为:

AND EXISTS 
(SELECT Distinct PROJECTID
 From Milestone_History MH, Project_Milestone PM
 Where MH.MilestoneId = PM.ID
   AND MH.Projectid = PR.ID
   AND UPPER(PM.Description) = 'FEASIBILITY STUDY REQUIRED' 
   AND Actual IS NOT NULL 
   AND NOT EXISTS
   (SELECT Distinct MH2.ProjectID
    From Milestone_History MH2, Project_Milestone PM2
    Where MH2.MilestoneId = PM2.ID
      AND UPPER(PM2.Description) = 'PROJECT COMPLETE' 
      AND MH2.Actual IS NOT NULL
   )
)
于 2013-05-14T17:08:39.647 回答