2014-03-13 103 views
1

我現有的查詢看起來像:提高在Oracle SQL查詢性能

SELECT p.subcode as proc_subcode, 
     r.subcode as rv_subcode, 
     r.rlv, 
     f.cfid, 
     f.geozip, 
     p.proc, 
     p.sh_descr, 
     f.begproc, 
     f.endproc, 
     p.descr, 
     r.modi, 
     f.per25 
    FROM user.code p, user.relative r, user.frequency f 
WHERE f.ID = 'XOF' 
    AND f.GEOZIP = '200' 
    AND f.REL_DATE = '10-SEP-13' 
    AND p.proc IN ('A0021', 'A0080', 'A0090', 'A0100', 'A0110', 'A0120', 
     'A0130', 'A0140', 'A0160', 'A0170', 'A0180', 'A0190', 
     'A0200', 'A0210', 'A0225') 
    AND r.ID = f.ID 
    AND f.REL_DATE = r.REL_DATE 
    AND f.ID = p.ID 
    AND f.REL_DATE = p.REL_DATE 
    AND p.proc = r.proc 
    AND p.proc between f.begproc AND f.endproc 
    AND (('A0021' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0021' AND 
     r.PROC = 'A0021' AND f.CFID = '00') OR 
     ('A0080' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0080' AND 
     r.PROC = 'A0080' AND f.CFID = '00') OR 
     ('A0090' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0090' AND 
     r.PROC = 'A0090' AND f.CFID = '00') OR 
     ('A0100' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0100' AND 
     r.PROC = 'A0100' AND f.CFID = '00') OR 
     ('A0110' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0110' AND 
     r.PROC = 'A0110' AND f.CFID = '00') OR 
     ('A0120' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0120' AND 
     r.PROC = 'A0120' AND f.CFID = '00') OR 
     ('A0130' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0130' AND 
     r.PROC = 'A0130' AND f.CFID = '00') OR 
     ('A0140' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0140' AND 
     r.PROC = 'A0140' AND f.CFID = '00') OR 
     ('A0160' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0160' AND 
     r.PROC = 'A0160' AND f.CFID = '00') OR 
     ('A0170' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0170' AND 
     r.PROC = 'A0170' AND f.CFID = '00') OR 
     ('A0180' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0180' AND 
     r.PROC = 'A0180' AND f.CFID = '00') OR 
     ('A0190' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0190' AND 
     r.PROC = 'A0190' AND f.CFID = '00') OR 
     ('A0200' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0200' AND 
     r.PROC = 'A0200' AND f.CFID = '00') OR 
     ('A0210' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0210' AND 
     r.PROC = 'A0210' AND f.CFID = '00') OR 
     ('A0225' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0225' AND 
     r.PROC = 'A0225' AND f.CFID = '00')) 
ORDER BY p.proc, r.modi, f.REL_DATE asc 

上面的查詢效果很好,不過,我計劃增加p.proc數百範圍內,爲前。它會像A0021-A1000一樣。所以,我想改善sql查詢性能。

任何人都可以幫忙嗎?

編輯1:

我想可能的解決辦法是刪除子句p.proc和利用之間。雖然我不確定最後的AND條件。

編輯2:

查詢

使用所有的某一特定區域的醫療費用geozip和傳球的代碼,爲前我基本上得到解釋。 A0021意味着手術代碼& 200意味着紐約& 2013年9月10日是發佈日期並獲得稱爲XOF的產品結果。

+2

我刪除了mysql標籤,因爲問題是明確的關於Oracle。 –

+0

您能向我們展示數據並解釋您的查詢的含義嗎? – MikkaRin

+1

「湯姆斯規則#1:永遠不要將字符串與日期和日期進行比較,總是將 字符串與字符串進行比較並將日期與日期進行比較!」 –

回答

1

首先

WHERE f.ID = 'XOF' 
    AND f.GEOZIP = '200' 
    AND f.REL_DATE = '10-SEP-13' 
    AND p.proc IN ('A0021', 'A0080', 'A0090', 'A0100', 'A0110', 'A0120', 
     'A0130', 'A0140', 'A0160', 'A0170', 'A0180', 'A0190', 
     'A0200', 'A0210', 'A0225') 
    AND r.ID = f.ID 
    AND f.REL_DATE = r.REL_DATE 
    AND f.ID = p.ID 
    AND f.REL_DATE = p.REL_DATE 
    AND p.proc = r.proc 
    AND p.proc between f.begproc AND f.endproc 
    AND (('A0021' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0021' AND 
     r.PROC = 'A0021' AND f.CFID = '00') OR 
     ('A0080' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0080' AND 
     r.PROC = 'A0080' AND f.CFID = '00') OR 
     ('A0090' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0090' AND 
     r.PROC = 'A0090' AND f.CFID = '00') OR.... 
在查詢p.proc = r.proc

。所以你不需要每次寫這些語句:

('A0090' BETWEEN f.BEGPROC AND f.ENDPROC AND p.PROC = 'A0090' AND 
    r.PROC = 'A0090' AND f.CFID = '00') OR 

在所有這些語句中也f.CFID = '00'。你不需要在每個陳述中寫出它。目前,我認爲所有你需要的是:

WHERE f.ID = 'XOF' 
     AND f.GEOZIP = '200' 
     AND f.REL_DATE = '10-SEP-13' 
     AND p.proc IN ('A0021', 'A0080', 'A0090', 'A0100', 'A0110', 'A0120', 
      'A0130', 'A0140', 'A0160', 'A0170', 'A0180', 'A0190', 
      'A0200', 'A0210', 'A0225') 
     AND r.ID = f.ID 
     AND f.REL_DATE = r.REL_DATE 
     AND f.ID = p.ID 
     AND f.REL_DATE = p.REL_DATE 
     AND p.proc = r.proc 
     AND p.proc between f.begproc AND f.endproc 
     AND f.CFID='00' 

這4所陳述

  AND p.proc IN ('A0021', 'A0080', 'A0090', 'A0100', 'A0110', 'A0120', 
       'A0130', 'A0140', 'A0160', 'A0170', 'A0180', 'A0190', 
       'A0200', 'A0210', 'A0225') 
      AND p.proc = r.proc 
      AND p.proc between f.begproc AND f.endproc 
      AND f.CFID='00' 

做出相同的是,所有這些BETWEEEN語句。

請檢查您的數據查詢

+0

謝謝MikkaRin。有沒有辦法避免p.proc IN子句。我的用戶可以在範圍內輸入1000個代碼,例如。 A0021-A1000。 – dang

+0

此外,f.CFID = '00'並不總是恆定的,這取決於查詢,它可能成爲f.CFID ='01'爲不同的代碼 – dang

+0

我認爲沒有辦法避免IN子句,因爲你存儲'proc '在'string'中。對於CFID,你可以這樣做:AND((p.proc IN(...)AND f.CFID = '00')OR(p.proc IN(...)AND f.CFID = '01 '))AND ....' – MikkaRin