简体   繁体   中英

Oracle query optimization recommendation

Below query is just taking long time and the below predicate is used only to get unique records, as such was wondering is there a different way to rewrite the same query without calling the below predicate multiple times, to get the unique ID.

select max(c.id) from plocation c where c.ids = y.ids and c.idc = y.idc)
select max(cr.id) from plocation_log cr where cr.ids = yt.ids and cr.idc = yt.idc)
select max(pr.id) from patentpr where pr.ids = p.ids and pr.idc = p.idc)           

My full sample query

SELECT to_char(p.pid) AS patentid,
       p.name,
       x.dept,
       y.location
  FROM patent p
  JOIN pdetails x ON p.pid = x.pid  AND x.isactive = 1
  JOIN plocation y
            ON y.idr = p.idr
           AND y.idc = p.idc
           AND y.id = *(select max(c.id) from plocation c where c.ids = y.ids and c.idc = y.idc)*
           AND y.idopstype in (36, 37)
   JOIN plocation_log yt
            ON yt.idr = y.idr
           AND yt.idc= y.idc
           AND yt.id = *(select max(cr.id) from plocation_log cr where cr.ids = yt.ids and cr.idc = yt.idc)*
           AND yt.idopstype in (36,37)
WHERE
      p.idp IN (10,20,30)
   AND p.id = *(select max(pr.id) from patent pr where pr.ids = p.ids and pr.idc = p.idc)*
   AND p.idopstype in (36,37)

As commented by The Impaler, one option is to use analytic functions instead of correlated subqueries. The idea is to rank records within subqueries using RANK() , then filter in the outer query (join conditions or WHERE clause).

Consider:

SELECT to_char(p.pid) AS patentid,
       p.name,
       x.dept,
       y.location
  FROM (SELECT p.*, RANK() OVER(PARTITION BY ids, idc ORDER BY id) rn FROM patinet) p
  JOIN pdetails x ON p.pid = x.pid  AND x.isactive = 1
  JOIN (SELECT y.*, RANK() OVER(PARTITION BY ids, idc ORDER BY id) rn FROM plocation y) y
            ON y.idr = p.idr
           AND y.idc = p.idc
           AND y.idopstype in (36, 37)
           AND y.rn = 1
   JOIN (SELECT y.*, RANK() OVER(PARTITION BY ids, idc ORDER BY id) rn FROM plocation_log yt) yt
            ON yt.idr = y.idr
           AND yt.idc= y.idc
           AND yt.idopstype in (36,37)
           AND yt.rn = 1
WHERE
   p.idp IN (10,20,30)
   AND p.idopstype in (36,37)
   AND p.rn = 1
   

Consider joining to aggregate CTEs to calculate MAX values per group once as opposed to rowwise MAX calculation for every outer query row. Also, be sure to use more informative table aliases instead of a, b, c or x, y, z style.

WITH loc_max AS
  (select ids, idc, max(id) as max_id from plocation group ids, idc)    
 ,   log_max AS    
  (select ids, idc, max(id) as max_id from plocation_log group by ids, idc)
 ,   pat_max AS
  (select ids, idc, max(id) as max_id from patent pr group by ids, idc)

SELECT to_char(pat.pid) AS patentid
       , pat.name
       , det.dept
       , loc.location
  FROM patent pat
  JOIN pdetails det
    ON pat.pid  = det.pid  
    AND det.isactive = 1
  JOIN plocation loc
    ON  loc.idr = pat.idr
    AND loc.idc = pat.idc
    AND loc.idopstype IN (36, 37)
  JOIN loc_max                              -- ADDED CTE JOIN
    ON  loc.id  = loc_max.max_id
    AND loc.ids = loc_max.ids 
    AND loc.idc = loc_max.idc
   
  JOIN plocation_log log
    ON  log.idr = log.idr
    AND log.idc = log.idc
    AND log.idopstype in (36,37)
  JOIN log_max                              -- ADDED CTE JOIN
    ON  log.id  = log_max.max_id
    AND log.ids = log_max.ids
    AND log.idc = log_max.idc

  JOIN pat_max                              -- ADDED CTE JOIN
    ON  pat.id  = pat_max.max_id
    AND pat.ids = pat_max.ids 
    AND pat.idc = pat_max.idc

WHERE pat.idp IN (10, 20, 30)
  AND pat.idopstype IN (36, 37)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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