2013-05-14 138 views
2

我有一些SQL,在这个问题中添加所有语句太多了,我试图改进以减少系统速度。PL/SQL Case语句 - IS NULL

在PL/SQL的一部分,有一个并存包含一个子句和NOT EXISTS条款。

这两个条款都包含案例陈述。在案件陈述的部分结束后,有一个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)) 

回答

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的行为,或者这是在未经清理的情况下沿途更新的补遗代码。

+0

+1 GMTA :)我不知道是要删除我的,还是把它作为一个稍微不同的方式说出同样的话。 – 2013-05-14 17:12:47

+0

@MarkBannister这里明确收敛的解释=) – 2013-05-15 07:40:19

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 

- 虽然本身OK,矛盾的两个以前的三个条件。写为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 

- 这既是更清晰,更简洁(并且排除了两个从以前的parenthesised子句中的三个条件)。

下一个条件:

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 -

NOT EXISTS子句可以简单地通过改变And MH2.ProjectID = MH.ProjectIDAnd MH2.ProjectID = PR.ProjectID被包括在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 
    ) 
)