繁体   English   中英

将子查询变成联接

[英]Turning a sub-query into a join

我有一个运行非常慢的子查询,但我不知道如何将其编写为联接以加快速度。 子查询在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) 

我已经单独测试了子查询,它快速拉动了必要的PIDMS照明,但是一旦我将其编写为子查询,就会减慢整个查询的速度。 我过去曾多次遇到此问题,因此如果有人知道其背后的逻辑会有所帮助。

DBMS-ORACLE

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 ,以防止在结果中出现重复项。

首先,您似乎在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   

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM