PL / SQL案例陈述 - IS NULL

时间:2013-05-14 16:06:51

标签: plsql case

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

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

这两个条款都包含 Case 语句。在case语句的 End 部分之后,有一个 IS NOT NULL IS 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))

2 个答案:

答案 0 :(得分:3)

CASE...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的行为,或者这是在未经清理的情况下一直更新的残余代码。

答案 1 :(得分: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

- 虽然(再次)OK本身,但由于先前的条件,基本上是多余的;它可以改写为:

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 EXISTS子句中的EXISTS子句执行得更快一些,因为只有EXISTS子句的其余部分是真。

与先前的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
   )
)