2016-07-22 64 views
1

我做出的Oracle 11g數據庫HAVING子句不工作

 SELECT DISTINCT JOC_FIN_CLTH_DFCT_LOT.LOT_NO, 
        I.ISSUE_DATE, 
        R.PROC_DESC, 
        R.RECV_DATE, 
        M.DFCT_DATE, 
        JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 
    FROM JOC_FIN_CLTH_DFCT_LOT, 
      JOC_FIN_CLTH_DFCT_MAIN M, 
      JOC_DAILY_FABRC_RECV_FOLD R, 
      JOC_LOT_ISSUE_REG I 
    WHERE  M.FCD_MAIN_ID = JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 
      AND R.LOT_NO = JOC_FIN_CLTH_DFCT_LOT.LOT_NO 
      AND I.LOT_NO = R.LOT_NO 
      AND I.LOT_YEAR = R.LOT_YEAR 
      AND JOC_FIN_CLTH_DFCT_LOT.LOT_YEAR = R.LOT_YEAR 
      AND JOC_FIN_CLTH_DFCT_LOT.LOT_YEAR = '1213' 
      AND JOC_FIN_CLTH_DFCT_LOT.FCDL_ID IN 
        ( SELECT MIN (DFCT_LOT.FCDL_ID) 
    FROM JOC_FIN_CLTH_DFCT_LOT DFCT_LOT, JOC_FIN_CLTH_DFCT_MAIN DFT_MAIN 
    WHERE DFCT_LOT.FCD_MAIN_ID IN (DFT_MAIN.FCD_MAIN_ID) 
GROUP BY DFCT_LOT.FCD_MAIN_ID) 
ORDER BY JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 

此查詢這2秒內沒有檢索數據。行= 5100 但是當我在我的前端應用程序中使用此查詢需要太多時間,以便排除故障後,我發現子查詢原因的問題時,數據檢索,所以我簡化此查詢

SELECT DISTINCT DFCT_LOT.LOT_NO, 
        I.ISSUE_DATE, 
        R.PROC_DESC, 
        R.RECV_DATE, 
        M.DFCT_DATE, 
        DFCT_LOT.FCD_MAIN_ID 
    FROM JOC_FIN_CLTH_DFCT_LOT DFCT_LOT, 
      JOC_FIN_CLTH_DFCT_MAIN M, 
      JOC_DAILY_FABRC_RECV_FOLD R, 
      JOC_LOT_ISSUE_REG I, 
      JOC_FIN_CLTH_DFCT_MAIN DFT_MAIN 
    WHERE  M.FCD_MAIN_ID = DFCT_LOT.FCD_MAIN_ID 
      AND R.LOT_NO = DFCT_LOT.LOT_NO 
      AND I.LOT_NO = R.LOT_NO 
      AND I.LOT_YEAR = R.LOT_YEAR 
      AND DFCT_LOT.LOT_YEAR = R.LOT_YEAR 
      AND DFCT_LOT.LOT_YEAR = '1213' 
      AND DFCT_LOT.FCD_MAIN_ID IN (DFT_MAIN.FCD_MAIN_ID) 

GROUP BY DFCT_LOT.FCDL_ID, 
      DFCT_LOT.FCD_MAIN_ID, 
      DFCT_LOT.LOT_NO, 
      I.ISSUE_DATE, 
      R.PROC_DESC, 
      R.RECV_DATE, 
      M.DFCT_DATE, 
      DFCT_LOT.FCD_MAIN_ID 
HAVING DFCT_LOT.FCDL_ID in MIN (DFCT_LOT.FCDL_ID) 
ORDER BY DFCT_LOT.FCD_MAIN_ID 

這是簡化的形式以上查詢但行數增加 no.of rows = 5578但我知道實際沒有。行= having子句5100 不在這裏工作 親切看着我的查詢,並引導我

+0

'min'返回一個值,並且您正在使用'in'? –

+0

所以我用它呢? – usman

+0

爲什麼不只是'='? –

回答

1

在你的第二個查詢,你作爲M加入表JOC_FIN_CLTH_DFCT_MAIN第二次,一次,一次作爲DFCT_LOT。在第二個查詢的SELECT列表中,您從M開始的第一列和從DFCT_LOT開始的最後一列。

但在第一個查詢中,它們都來自同一個M表。如果JOC_FIN_CLTH_DFCT_MAIN中的記錄不止FCD_MAIN_ID,那麼這會在第二個查詢中產生更多組合,這就解釋了爲什麼您有更多的結果。

但還有其他幾個不同點。在第二個查詢中,您比第一個查詢中的列數多得多。而且,MIN (DFCT_LOT.FCDL_ID)在第二個查詢中沒有任何意義,因爲它已經分組了,所以它與DFCT_LOT.FCDL_ID完全一樣。因此,HAVING條款只是一個簡單的同義反復,你可以放棄它,仍然得到相同的結果。

如果您確定第一個查詢給你想要的結果,那麼我會建議用不同的方式來實現它的可能的優化:

SELECT  DISTINCT 
      L.LOT_NO, 
      I.ISSUE_DATE, 
      R.PROC_DESC, 
      R.RECV_DATE, 
      L.DFCT_DATE, 
      L.FCD_MAIN_ID, 
FROM  (SELECT  L.FCD_MAIN_ID, 
         L.LOT_NO, 
         L.LOT_YEAR, 
         M.DFCT_DATE, 
         ROW_NUMBER() OVER (PARTITION BY L.FCD_MAIN_ID 
              ORDER BY L.FCDL_ID) AS RN 
      FROM  JOC_FIN_CLTH_DFCT_LOT L, 
      INNER JOIN JOC_FIN_CLTH_DFCT_MAIN M 
        ON M.FCD_MAIN_ID = L.FCD_MAIN_ID 
      ) L 
INNER JOIN JOC_DAILY_FABRC_RECV_FOLD R 
     ON R.LOT_NO = L.LOT_NO 
     AND R.LOT_YEAR = L.LOT_YEAR 
INNER JOIN JOC_LOT_ISSUE_REG I 
     ON I.LOT_NO = R.LOT_NO 
     AND I.LOT_YEAR = R.LOT_YEAR 
WHERE  L.LOT_YEAR = '1213' 
     AND L.RN = 1 
ORDER BY L.FCD_MAIN_ID 

請注意,我已經使用了ANSI/ISO語法加入,我強烈建議你這樣做。在WHERE條款中定義加入條件是八十年代的事情;不要這樣做。一旦習慣了ANSI/ISO語法,查詢變得更加可讀。

建議的查詢選擇子查詢中JOC_FIN_CLTH_DFCT_LOTJOC_FIN_CLTH_DFCT_MAIN所需的所有列,這樣您不必再次包含這些表。

主要技巧是使用ROW_NUMBER窗口函數,該函數根據PARTITION子句給出序列號。然後,外部查詢將過濾僅獲得編號爲1的記錄,這些記錄是FCD_MAIN_ID的值對於給定的FCDL_ID最小的記錄。