2014-01-05 183 views
2

我有,因爲correlated subquery糟糕表現查詢,我想取代它WIZ non-correlated subquery。如何做到這一點:如何用非相關子查詢替換相關的子查詢?

我的查詢:

select a.emp_num, a.name , b.cont_date 
from main_emp a INNER JOIN main_cont b 
ON a.emp_num = b.emp_num AND a.calc_year = b.calc_year 

join 
(
    select emp_num,calc_year, max(bb.cont_date) AS max_date from main_cont bb 
    GROUP BY emp_num,calc_year 
) bb_max 
on a.emp_num = bb_max.emp_num and a.calc_year = bb_max.calc_year and b.cont_date = bb_max.max_date 

where 
(0 = (select count(*) from main_serv x where x.emp_num = a.emp_num and x.calc_year = a.calc_year) 
    or b.cont_date > (select max(y.ser_date) from main_serv y where y.emp_num = a.emp_num and y.calc_year = a.calc_year)) -- The problem here 
and a.calc_year = 2015 
order by 1 

現在我想這個轉換子查詢:

(0 = (select count(*) from main_serv x where x.emp_num = a.emp_num and x.calc_year = a.calc_year) 
     or b.cont_date > (select max(y.ser_date) from main_serv y where y.emp_num = a.emp_num and y.calc_year = a.calc_year)) 

加入這樣的:

join 
    (
     select emp_num,calc_year, max(bb.cont_date) AS max_date from main_cont bb 
     GROUP BY emp_num,calc_year 
    ) bb_max 
    on a.emp_num = bb_max.emp_num and a.calc_year = bb_max.calc_year and b.cont_date = bb_max.max_date 

,但我不如何做到這一點,因爲我有((0 =(subquery) OR (subquery))

+1

你可以這樣做:'INNER JOIN ( SELECT COUNT(*)AS計數,MAX(y.ser_date)AS MAXDATE 從main_serv X 其中x.emp_num = a.emp_num和x.calc_year =一個。 calc_year )tt ON tt.count = 0 AND b.cont_date

+0

@MahmoudGamal:但是我有'OR'而不是'AND' –

+0

和'b.cont_date>''不''' –

回答

1

像這樣:

SELECT 
    a.emp_num, 
    a.name, 
    b.cont_date 
FROM main_emp a 
INNER JOIN main_cont b ON a.emp_num = b.emp_num AND a.calc_year = b.calc_year 
INNER JOIN 
(
    SELECT emp_num,calc_year, max(bb.cont_date) AS max_date 
    from main_cont bb 
    GROUP BY emp_num,calc_year 
) bb_max 
on a.emp_num = bb_max.emp_num and a.calc_year = bb_max.calc_year 
           and b.cont_date = bb_max.max_date 
INNER JOIN 
( 
    SELECT emp_num, calc_year, count(*) AS count, max(ser_date) AS MaxDate 
    from main_serv 
    WHERE calc_year IS NOT NULL 
    GROUP BY emp_num, calc_year 
) x ON x.count = 0 OR b.cont_date > x.MaxDate 
    AND x.emp_num = a.emp_num 
    AND x.calc_year = a.calc_year 
where a.calc_year = 2015 
order by 1 
+0

感謝很多:) 但我現在得到行!與子查詢相反! 我想原因是'calc_year'是'main_serv'表空 –

+1

@just_name - 嘗試添加'WHERE calc_year IS NOT NULL' –

2

我相信你的WHERE子句

這部分
(0 = (select count(*) from main_serv x where x.emp_num = a.emp_num and x.calc_year = a.calc_year) 
    or b.cont_date > (select max(y.ser_date) from main_serv y where y.emp_num = a.emp_num and y.calc_year = a.calc_year)) 

可以呈現爲

有在main_serv
OR
沒有行有在main_serv其中ser_date是等於或大於b.cont_date更大任何行。

相信脫節的第二部分涵蓋了完整的狀態,因爲當有main_serv沒有行,肯定會有不符合條件的第二部分行,並且如果在main_serv任何行,這將是決定結果的第二部分條件。所以,我會改寫這樣整個析取部分:

not exists (
    select * 
    from main_serv as x 
    where x.emp_num = a.emp_num 
    and x.calc_year = a.calc_year 
    and x.ser_date >= b.cont_date 
) 

此子查詢仍然是相關的主查詢,但它不會執行任何聚合,可能整體會在你的版本有所改進呢。