我必须将相关的子查询转换为性能问题的非相关子查询。
像那样:相关子查询:(太慢)返回4000行
SELECT a.personid,a.name,b.conid,d.condat,e.connam
FROM main_empr a INNER JOIN coninr b
ON a.personid = b.personid AND a.calc_year = b.calc_year
INNER JOIN mainconinr c
ON b.conid = c.conid
INNER JOIN coninr d
ON a.personid = d.personid AND a.calc_year = d.calc_year
INNER JOIN mainconinr e
ON d.conid = e.conid
WHERE c.active_flag = 1 and c.endreward_flag = 1
AND d.condat = (SELECT MIN(bb.condat) FROM coninr bb WHERE bb.personid = b.personid AND bb.calc_year = b.calc_year AND ((bb.conid > 0 AND bb.conid < 4 ) OR (bb.conid IN(16,6) )) )
AND b.condat = (SELECT MAX(bb.condat) FROM coninr bb WHERE bb.personid = b.personid AND bb.calc_year = b.calc_year AND ((bb.conid > 0 AND bb.conid < 4 ) OR (bb.conid IN(16,6) )) )
AND ( 0 = ( SELECT COUNT(*) FROM servmain x WHERE x.personid = a.personid AND x.calc_year = a.calc_year )
OR b.condat > ( SELECT MAX(x.serv_date) FROM servmain x WHERE x.personid = a.personid AND x.calc_year = a.calc_year ) )
AND a.calc_year = 2018
非相关查询:返回约12300行 !!
SELECT a.personid,a.name,b.conid,d.condat,e.connam
FROM main_empr a INNER JOIN
coninr b
ON a.personid = b.personid AND a.calc_year = b.calc_year
INNER JOIN mainconinr c
ON b.conid = c.conid
INNER JOIN coninr d
ON a.personid = d.personid AND a.calc_year = d.calc_year
INNER JOIN mainconinr e ON d.conid = e.conid
INNER JOIN
(SELECT MAX(bb.condat) AS condat ,bb.personid,bb.calc_year ,bb.conid
FROM coninr bb
GROUP BY bb.personid,bb.calc_year,bb.conid
)Max_cont
ON Max_cont.personid = b.personid AND Max_cont.calc_year = b.calc_year AND Max_cont.condat = b.condat AND ((Max_cont.conid > 0 AND Max_cont.conid < 4 ) OR (Max_cont.conid IN(16,6) ))
INNER JOIN
(SELECT MIN(dd.condat) AS condat ,dd.personid,dd.calc_year,dd.conid
FROM coninr dd GROUP BY dd.personid,dd.calc_year,dd.conid
)Min_cont
ON Min_cont.personid = d.personid AND Min_cont.calc_year = d.calc_year AND Min_cont.condat = d.condat AND ((Min_cont.conid > 0 AND Min_cont.conid < 4 ) OR (Min_cont.conid IN(16,6) ))
WHERE c.active_flag = 1 and c.endreward_flag = 1
AND ( 0 = ( SELECT COUNT(*) FROM servmain x WHERE x.personid = a.personid AND x.calc_year = a.calc_year )
OR b.condat > ( SELECT MAX(x.serv_date) FROM servmain x WHERE x.personid = a.personid AND x.calc_year = a.calc_year ) )
AND a.calc_year = 2018
问题是:
我两次使用coninr
表来获取同一行中的最后一个和第一个合同日期。
它在第一个查询中工作正常,但由于相关的子查询,它很慢,但在第二个查询中,它为同一个人带来了多个行,其中一行是第一个合同日期,另一个是最后一个!!
如何解决这个问题?
答案 0 :(得分:2)
这看起来很合理,但我无法知道它的表现如何:
SELECT a.personid,a.name,b.conid,d.condat,e.connam
FROM main_empr a INNER JOIN coninr b
ON a.personid = b.personid AND a.calc_year = b.calc_year
INNER JOIN mainconinr c
ON b.conid = c.conid
INNER JOIN coninr d
ON a.personid = d.personid AND a.calc_year = d.calc_year
INNER JOIN mainconinr e
ON d.conid = e.conid
inner join
(
SELECT bb.personid, bb.calc_year, bb.conid, MIN(bb.condat) MinDate, MAX(bb.condat) MaxDate
FROM coninr bb WHERE
where (bb.conid > 0 and bb.conid < 4) or (bb.conid in (6, 16))
group by bb.personid, bb.calc_year, bb.conid
) zz on d.concat = zz.MinDate and b.condat = zz.MaxDate and b.personid = zz.personid and b.calc_year = zz.calc_year
left outer join
(
select s.personid, s.calc_year, max(s.serv_date) MaxServDate
from servmain s
group by s.personid, s.calc_year
) s on a.personid = s.personid and a.calc_year = s.calc_year
WHERE c.active_flag = 1 and c.endreward_flag = 1
and (s.MaxServDate is null or b.condat ? s.MaxServDate
AND a.calc_year = 2018
您不需要对表coninr进行两次查询,您可以在group by的同一查询中获得min和max。此外,对于ServMain,执行左外连接并放入其中为null(相当于count(*)= 0)或小于b.condat的位置来处理。