Search code examples
sqloracle-databasequery-optimizationgreatest-n-per-groupwindow-functions

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)

Solution

  • 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)