2013-05-14 64 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 
    ) 
)