oracle查询优化建议

1bqhqjot  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(268)

below查询只需要很长时间,而below predicate 只用于获取唯一的记录,因此想知道是否有其他方法可以重写同一个查询而不多次调用below predicate 来获取唯一的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)

我的完整示例查询

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

yuvru6vn1#

考虑加入聚合CTE以计算 MAX 每组值一次,而不是按行 MAX 计算每个外部查询行。另外,请确保使用更多的信息表别名,而不是 a, b, c 或者 x, y, z 风格。

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)
06odsfpq

06odsfpq2#

正如impaler所评论的,一种选择是使用分析函数而不是相关的子查询。其思想是使用 RANK() ,然后筛选外部查询(连接条件或 WHERE 条款)。
考虑:

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

相关问题