简体   繁体   English

将子查询变成联接

[英]Turning a sub-query into a join

I have a sub query that is running extremely slow but I can't figure out how to write it as a join to speed it up. 我有一个运行非常慢的子查询,但我不知道如何将其编写为联接以加快速度。 The subquery is below the AND OR section in the WHERE clause. 子查询在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) 

I've tested the subquery alone and it pulls the neccessary PIDMS lighting quick but as soon as I write it as a subquery it slows the entire query down. 我已经单独测试了子查询,它快速拉动了必要的PIDMS照明,但是一旦我将其编写为子查询,就会减慢整个查询的速度。 I've had this problem multiple times in the past so if anyone knows the logic behind it that would be helpful. 我过去曾多次遇到此问题,因此如果有人知道其背后的逻辑会有所帮助。

DBMS - ORACLE DBMS-ORACLE

The usual way to turn NOT IN into a JOIN is this: NOT IN变成JOIN的通常方法是:

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

is: 是:

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

Depending on the structure of the subquery, it may be possible to move its WHERE clauses into the ON clause of the JOIN, eg 根据子查询的结构,可能将其WHERE子句移到JOIN的ON子句中,例如

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

If the subquery can have multiple matches for rows in table1 , you should use SELECT DISTINCT in the subquery to prevent duplicates from appearing in the result. 如果子查询可以对table1中的行具有多个匹配项,则应在子查询中使用SELECT DISTINCT ,以防止在结果中出现重复项。

First, you seem to have an extra table1 in the from clause. 首先,您似乎在from子句中有一个额外的table1 This is probably causing your problems. 这可能是造成您的问题的原因。 Consider this instead: 考虑一下这个:

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

The following converts this version to a left outer join . 以下内容将此版本转换为left outer join The where clause then does the "not exists" part of the query: 然后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