由于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))
答案 0 :(得分: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
)
此子查询仍然与主查询相关,但它不会执行任何聚合,并且总体上可能比您的版本有所改进。
答案 1 :(得分: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