Select workorders (via parameters) and their children

百般思念 提交于 2020-12-27 06:43:24

问题


I have a Oracle 12c query that will eventually be used in a BIRT report (in IBM's Maximo Asset Management platform).


The query/report will retrieve records as follows:

  1. Retrieve workorders based on the parameters that were selected by the user.
    • All of the parameters are optional.
    • For testing purposes, I'm using bind variables as parameters (in Toad for Oracle).
    • It doesn't matter if the workorders are parents, children, or neither.
  2. Of the workorders that were retrieved, also select any children of those workorders.
    • There are only two levels to the parent/child hierarchy: parents and children (no grandchildren, etc.)

The output looks like this:

The blue boxes show examples of parents with children.


The query:

--short form definitions:
--wo   = workorder
--act  = actual (actual cost, actual date, etc.)
--pmtr = parameters

with 
wo_pmtr as (  --WOs filtered by parameters
select
    wonum,
    parent,
    hierarchypath,
    classstructureid,
    division,
    worktype,
    status, 
    trunc(actstart)  as actstart,
    trunc(actfinish) as actfinish,
    actlabcost,
    actmatcost,
    actservcost,
    acttoolcost,
    acttotalcost   
from
    workorder wo
where   
    --using bind variables as parameters in Toad
        (:wonum            is null     or wonum             = :wonum)
    and (:division         is null     or division          = :division)
    and (:worktype         is null     or worktype          = :worktype)
    and (:status           is null     or status            = :status)
    and (:actstart         is null     or trunc(actstart)  >= :actstart)
    and (:actfinish        is null     or trunc(actfinish) <= :actfinish)

    --retrieve workorders where the classification matches the parameter 
    --and retrieve any child classifications too
    --the classification hierarchy is not to be confused with the workorder hierarchy

    and (:classstructureid is null     or (exists (select 1 from classancestor where ((ancestor = :classstructureid)) and (classstructureid=wo.classstructureid))))
)

select
    wo_pmtr.wonum,
    wo_pmtr.parent,
    wo_pmtr.hierarchypath,
    wo_pmtr.classstructureid,
    wo_pmtr.division,
    wo_pmtr.worktype,
    wo_pmtr.status, 
    wo_pmtr.actstart,
    wo_pmtr.actfinish,
    wo_pmtr.actlabcost,
    wo_pmtr.actmatcost,
    wo_pmtr.actservcost,
    wo_pmtr.acttoolcost,
    wo_pmtr.acttotalcost,
    coalesce(wo_pmtr.parent, wo_pmtr.wonum) parent_coalesced
from
    wo_pmtr      --WOs filtered by parameters
union            --union will remove duplicates (unlike union all)
select           --select children of the filtered WOs
    wo.wonum,
    wo.parent,
    wo.hierarchypath,
    wo.classstructureid,
    wo.division,
    wo.worktype,
    wo.status, 
    trunc(wo.actstart)  as actstart,
    trunc(wo.actfinish) as actfinish,
    wo.actlabcost,
    wo.actmatcost,
    wo.actservcost,
    wo.acttoolcost,
    wo.acttotalcost,
    coalesce(wo.parent, wo.wonum) parent_coalesced
from
    workorder wo  --select from the base workorder table *without* filtering by the parameters
left join
    wo_pmtr
    on wo.parent = wo_pmtr.wonum
where
    wo.parent         is not null  --where WO is a child
    and wo_pmtr.wonum is not null  --where WO is a child of the filtered WOs 
                                   --caution: some of those workorders might have already been selected via the parameters in the first query
                                   --we need to eliminate duplicates if they exist (via the union)
order by
    parent_coalesced, 
    hierarchypath

db<>fiddle here


Question:

The query makes several full table scans:

Is there a way to reduce the number of full table scans to improve performance?


回答1:


There are many indexes that you can use on the WORKORDER table. What stands out in your query is that you're not referring to the SITEID column which should almost always come with the WONUM as together they compose the "primary key", which in Oracle Maximo is a unique index.

You can confirm this by running this query:

   select attributename from maxattribute where objectname='WORKORDER' AND PRIMARYKEYCOLSEQ IS NOT NULL;

Also, a good practice is to identify which indexes you will need to query the needed data. You can have a look at the table's indexes with your favorite SQL tool or from the Database Configuration Maximo application.




回答2:


full table scans are only required if no proper index is in place. So create such and you will see that the full table scans disappear



来源:https://stackoverflow.com/questions/64849333/select-workorders-via-parameters-and-their-children

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!