2013-04-24 47 views
0

我有一個運行速度非常慢的子查詢,但我無法弄清楚如何將它作爲連接編寫來加速它。子查詢位於WHERE子句中的AND OR部分的下面。將子查詢轉變爲加入

select 'Fall ' || (x.syrsdhe_year - 1) "Term", 
     count(x.syrsdhe_ssn_id) "Cohort", 
     (sum((select '1' from dual where r1.syrsdhe_year = (x.syrsdhe_year)))/  count(x.syrsdhe_ssn_id))*100 "Fall_to_Spring", 
     (sum((select '1' from dual where r2.syrsdhe_year = (x.syrsdhe_year + 1)))/count(x.syrsdhe_ssn_id))*100 "One_Year", 
     (sum((select '1' from dual where r3.syrsdhe_year = (x.syrsdhe_year + 2)))/count(x.syrsdhe_ssn_id))*100 "Two_Year" 

from irdeptq.syrsdhe x 
left join irdeptq.syrsdhe r1 
     on r1.syrsdhe_ssn_id = x.syrsdhe_ssn_id 
     and r1.syrsdhe_term = '2' 
     and r1.syrsdhe_student_level in ('01','02','03','04') 
     and r1.syrsdhe_year = (x.syrsdhe_year) 
left join irdeptq.syrsdhe r2 
     on r2.syrsdhe_ssn_id = x.syrsdhe_ssn_id 
     and r2.syrsdhe_term = '1' 
     and r2.syrsdhe_student_level in ('01','02','03','04') 
     and r2.syrsdhe_year = (x.syrsdhe_year + 1) 
left join irdeptq.syrsdhe r3 
     on r3.syrsdhe_ssn_id = x.syrsdhe_ssn_id 
     and r3.syrsdhe_term = '1' 
     and r3.syrsdhe_student_level in ('01','02','03','04') 
     and r3.syrsdhe_year = (x.syrsdhe_year + 2) 



where x.syrsdhe_enroll_status = '01' 
    and x.syrsdhe_attend_status = '0' 
    and x.syrsdhe_degree_intent != '3' 
    and x.syrsdhe_term = '1' 
    and x.syrsdhe_year >= '2006' 
    and x.syrsdhe_housing is not null 
    and ((x.syrsdhe_year = '2006' and x.syrsdhe_pidm not in (select sgrchrt_pidm from sgrchrt where sgrchrt_term_code_eff = x.syrsdhe_banner_term and sgrchrt_chrt_code in ('HRC','SRC'))) 
    or (x.syrsdhe_year = '2007' and x.syrsdhe_pidm not in (select sgrchrt_pidm from sgrchrt where sgrchrt_term_code_eff = x.syrsdhe_banner_term and sgrchrt_chrt_code in ('HRC','SRC','SDRC'))) 
    or (x.syrsdhe_year = '2008' and x.syrsdhe_pidm not in (select sgrchrt_pidm from sgrchrt where sgrchrt_term_code_eff = x.syrsdhe_banner_term and sgrchrt_chrt_code in ('HRC','SRC','SDRC'))) 
    or (x.syrsdhe_year = '2009' and x.syrsdhe_pidm not in (select sgrchrt_pidm from sgrchrt where sgrchrt_term_code_eff = x.syrsdhe_banner_term and sgrchrt_chrt_code in ('HRC','SRC','SDRC'))) 
    or (x.syrsdhe_year = '2010' and x.syrsdhe_pidm not in (select sgrchrt_pidm from sgrchrt where sgrchrt_term_code_eff = x.syrsdhe_banner_term and sgrchrt_chrt_code in ('HRC','SRC','SDRC'))) 
    or (x.syrsdhe_year = '2011' and x.syrsdhe_pidm not in (select sgrchrt_pidm from sgrchrt where sgrchrt_term_code_eff = x.syrsdhe_banner_term and sgrchrt_chrt_code in ('HRC','SRC','SDRC','STEM'))) 
    or (x.syrsdhe_year = '2012' and x.syrsdhe_pidm not in (select sgrchrt_pidm from sgrchrt where sgrchrt_term_code_eff = x.syrsdhe_banner_term and sgrchrt_chrt_code in ('HRC','SDRC','STEM','EDGE'))) 
    or (x.syrsdhe_year = '2013' and x.syrsdhe_pidm not in (select sgrchrt_pidm from sgrchrt where sgrchrt_term_code_eff = x.syrsdhe_banner_term and sgrchrt_chrt_code in ('HRC','STEM','EDGE','STARS'))) 
    ) 
    **and x.syrsdhe_pidm not in (select rpratrm_pidm 
         from rpratrm where x.syrsdhe_banner_term = rpratrm_term_code 
         and x.syrsdhe_pidm = rpratrm_pidm 
         and rpratrm_paid_amt >0 
         and rpratrm_fund_code in ('HCSCH','HCFADJ','HCFULL','HCPRRM','HCBSCH','HCSUPP'))** 


    Group By 'Fall ' || (X.Syrsdhe_Year - 1) 
    order By 'Fall ' || (X.Syrsdhe_Year - 1) 

我單獨測試的子查詢,並將其拉neccessary PIDMS點燃快,但只要我寫它作爲一個子查詢它減緩了整個查詢了下來。過去我曾多次遇到過這個問題,所以如果有人知道它背後的邏輯會有所幫助。

DBMS - ORACLE

+1

你肯定總有這個子查詢的結果?看起來你必須改變它,否則你可能會有不希望的結果。顯示完整查詢請 – Sebas 2013-04-24 18:32:12

+0

看看NOT存在的結構。它通常比不在或左連接快得多。 – HLGEM 2013-04-24 18:33:49

+2

@HLGEM:...除了在MySQL中,左連接*往往會更快。 – 2013-04-24 18:34:41

回答

1

通常的辦法把NOT IN到JOIN是這樣的:

SELECT whatever 
FROM table1 
WHERE somecol NOT IN (SELECT othercol FROM ...) 

是:

SELECT whatever 
FROM table1 
LEFT JOIN (SELECT othercol FROM ...) t2 ON somecol = othercol 
WHERE othercol IS NULL 

取決於子查詢的結構,它可以是可能將其WHERE子句移入JOIN的ON子句中,例如

SELECT whatever 
FROM table1 
LEFT JOIN table2 ON somecol = othercol AND table2.date > '2013-04-01' 

如果子查詢可以有多個排在比賽table1,你應該在子查詢中使用SELECT DISTINCT防止重複出現在結果中。

0

首先,您似乎在from子句中有一個額外的table1。這可能會導致你的問題。代之以:

table1_id not in (select table2_id 
          from table2 
          where table1.table1_term = table2_term 
          and table2_paid_amt >0 
          ) 

以下將此版本轉換爲left outer join。然後where條款,那麼「不存在」查詢的一部分:

select . . . 
from table1 t1 left outer join 
    table2 t2 
    on t1.table1_term = t2.table2_term and 
     t2.table2_paid_amt > 0 
where t2.table2_id is null