2014-03-13 102 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