I have the following query, in this query, I am selecting the ebs tables, with a custom table which has header_id and populating the the data in a custom table XXREPORT_L1_TBL.
I want to tune this query.
[update] made changes to the query as bellow:
added an update statement at the end for these columns.
insert into XX.XXREPORT_L1_TBL ( ORDER_NUMBER
, LINE_NUMBER
, UOM
, CUSTOMER_LENGTH
, THEORETICAL_WEIGHT
, FINISH
, ORDER_QTY_PCS
, ORDER_QTY_KGS
, SALES_VALUE
, TOTAL_VALUE
, ORDERED_QUANTITY
, WIP_ENTITY_ID
, JOB_NAME
, JOB_TYPE
, JOB_STATUS
, JOB_RELEASED_DATE
, DATE_COMPLETED
, DATE_CLOSED
, JOB_CARD_QTY
, ALLOY
, PROFILE
, PROD_QTY_KGS
, COST_KGS_THEORY
, COST_KGS_ACTUAL
)
SELECT
---- Sales Order
xx.order_number
,xx.line_number
,xx.UOM,
xx.customer_length,
xx.theoretical_weight,
xx.finish,
xx.order_qty_pcs,
xx.order_qty_kgs,
xx.sales_value, -- total value / total kgs
xx.total_value, -- line total
xx.ordered_quantity,
-- Production
xx.wip_entity_id,
xx.job_name,
( select case when a.inventory_item_id = 5716770 and a.job_type='NOT CHILD' then 'PARENT'
when a.job_type='CHILD' and a.inventory_item_id is null then 'CHILD'
when a.job_type='NOT CHILD' and a.inventory_item_id is NOT null then 'NOT CHILD' END JOB_TYPE
from ( select disc2.wip_entity_id as wip_entity_id, decode ( nvl(disc2.attribute9,-1) , -1,'NOT CHILD', 'CHILD') job_type, oel.inventory_item_id
from APPS.wip_discrete_jobs disc2, APPS.oe_order_lines_all oel
where oel.line_id(+) = disc2.source_line_id
)a
where a.wip_entity_id = xx.wip_entity_id
) job_type,
( select decode ( xx.status_type, 6, 'Open',
3, 'Open',
4, 'Completed',
LU1.MEANING )
from APPS.FND_LOOKUP_VALUES LU1
where LU1.LOOKUP_TYPE = 'WIP_JOB_STATUS'
AND LU1.LOOKUP_CODE = xx.STATUS_TYPE
) job_status,
xx.job_released_date,
xx.date_completed,
xx.date_closed
,xx.net_quantity as job_card_qty
,xx.alloy
,xx.profile
,xx.prod_qty_kgs
-- Theoretical Order cost
,xx.cost_kgs_theory
-- Actual Order cost
,xx.cost_kgs_actual
from (
select a.*
-- Theoretical Order cost
, DECODE (a.qty_completed * a.customer_length * a.theoretical_weight,0,0,
a.TOT_THEORY_COST_RELIEVED/(a.qty_completed * a.customer_length * a.theoretical_weight) ) as cost_kgs_theory
-- Actual Order cost
, DECODE ( a.qty_completed * a.customer_length * a.theoretical_weight, 0, 0,
a.TOT_ACTUAL_COST_INCURRED/(a.qty_completed * a.customer_length * a.theoretical_weight )) as cost_kgs_actual
from (
select
-- Normal orders, INTERNAL Orders, Crimped Profile (parent jobs)
-- Sales Order
oeh.order_number as order_number
,oel.line_number
,oel.pricing_quantity_uom as UOM
,oel.attribute1 as customer_length
,oel.attribute6 as theoretical_weight
,oel.attribute5 as finish
,oel.attribute18 as order_qty_pcs
,oel.attribute7 as order_qty_kgs
,xx_om.GetLineUnitSellingPrice(oel.line_id) sales_value
,xx_om.GetHeaderUnitSellingPrice(oeh.header_id) total_value
,oel.ordered_quantity ordered_quantity
-- Production
, tbl0.qty_completed as qty_completed
,disc.wip_entity_id as wip_entity_id
,( select wip_entity_name from APPS.wip_entities ent
where ent.wip_entity_id = disc.wip_entity_id) job_name
,disc.status_type
,disc.date_released as job_released_date
, DECODE ( disc.date_completed, NULL, disc.date_completed,
-- my day Definition
to_date(to_char(to_date(TO_CHAR(disc.date_completed- interval '7' hour,'DD-MON-YYYY')||'00:00:00','DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS')) as date_completed
, DECODE ( disc.date_closed, NULL, disc.date_closed,
to_date(to_char(to_date(TO_CHAR(disc.date_closed- interval '7' hour,'DD-MON-YYYY')||'00:00:00','DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS')) as date_closed
, disc.net_quantity
, ( select opr2.quantity_completed
from APPS.wip_operations opr2
where opr2.wip_entity_id = disc.wip_entity_id
and opr2.operation_seq_num = (select max(opr.operation_seq_num)
from APPS.wip_operations opr, APPS.wip_discrete_jobs disc2
where opr.wip_entity_id = disc2.wip_entity_id
and disc2.wip_entity_id = disc.wip_entity_id))* oel.attribute1 * oel.attribute6 as prod_qty_kgs
,oel.attribute4 as alloy
,oel.attribute2 as profile
-- Theoretical Order cost
,tbl0.TOT_THEORY_COST_RELIEVED
-- Actual Order cost
,tbl0.TOT_ACTUAL_COST_INCURRED
from XX.XXREPORT_Lzero_TBL tbl0
join APPS.oe_order_headers_all oeh on oeh.header_id = tbl0.header_id
join APPS.oe_order_lines_all oel on oeh.org_id = oel.org_id and oeh.header_id = oel.header_id
join APPS.xx_assemblies asm on oel.line_id = asm.line_id
join APPS.wip_discrete_jobs disc on disc.primary_item_id = asm.inventory_item_id
where oel.link_to_line_id is null
union
-- Crimped Child Jobs
select
-- Sales Order
oeh.order_number as order_number
,oel.line_number
,oel.pricing_quantity_uom as UOM
,oel.attribute1 as customer_length
,oel.attribute6 as theoretical_weight
,oel.attribute5 as finish
,oel.attribute18 as order_qty_pcs
,oel.attribute7 as order_qty_kgs
,xx_om.GetLineUnitSellingPrice(oel.line_id) sales_value
,xx_om.GetHeaderUnitSellingPrice(oeh.header_id) total_value
,oel.ordered_quantity ordered_quantity
-- Production
, tbl0.qty_completed as qty_completed
,child_jobs.wip_entity_id as wip_entity_id
,( select wip_entity_name from APPS.wip_entities ent
where ent.wip_entity_id = child_jobs.wip_entity_id) job_name
,disc.status_type
,disc.date_released as job_released_date
, DECODE ( disc.date_completed, NULL, disc.date_completed,
to_date(to_char(to_date(TO_CHAR(disc.date_completed-interval '7' hour,'DD-MON-YYYY')||'00:00:00','DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS')) as date_completed
, DECODE ( disc.date_closed, NULL, disc.date_closed,
to_date(to_char(to_date(TO_CHAR(disc.date_closed-interval '7' hour,'DD-MON-YYYY')||'00:00:00','DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS')) as date_closed
, disc.net_quantity
, ( select opr2.quantity_completed
from APPS.wip_operations opr2
where opr2.wip_entity_id = disc.wip_entity_id
and opr2.operation_seq_num = (select max(opr.operation_seq_num)
from APPS.wip_operations opr, APPS.wip_discrete_jobs disc2
where opr.wip_entity_id = disc2.wip_entity_id
and disc.wip_entity_id = disc.wip_entity_id))* oel.attribute1 * oel.attribute6 as prod_qty_kgs
,oel.attribute4 as alloy
,oel.attribute2 as profile
-- Theoretical Order cost
,tbl0.TOT_THEORY_COST_RELIEVED
-- Actual Order cost
,tbl0.TOT_ACTUAL_COST_INCURRED
from XX.XXREPORT_Lzero_TBL tbl0
join APPS.oe_order_headers_all oeh on oeh.header_id = tbl0.header_id
join APPS.oe_order_lines_all oel on oeh.org_id = oel.org_id and oeh.header_id = oel.header_id
join APPS.xx_assemblies asm on oel.line_id = asm.line_id
join APPS.wip_discrete_jobs disc on disc.primary_item_id = asm.inventory_item_id
join ( select wdj2.source_line_id, wdj2.attribute9 child_wip, wdj2.wip_entity_id, wdj2.status_type status_type
from APPS.wip_discrete_jobs wdj2
where attribute9 IS NOT NULL ) child_jobs on child_jobs.child_wip = to_char(disc.wip_entity_id)
where oel.link_to_line_id is null
union
-- Orders with star (*) items need to pick profile and customer length etc from ego_configured_pr_agv view
select
-- Sales Order
oeh.order_number as order_number
,oel.line_number
,oel.pricing_quantity_uom as UOM
,to_char(agv.gx_cp_length) as customer_length
,to_char(agv.gx_cp_th_weight) as theoretical_weight
,agv.gx_cp_surfacetreatment as finish
,oel.attribute18 as order_qty_pcs
, to_char(agv.gx_cp_th_weight * agv.gx_cp_length * oel.ordered_quantity) as order_qty_kgs
,XX.xx_om.GetLineUnitSellingPrice(oel.line_id) sales_value
,XX.xx_om.GetHeaderUnitSellingPrice(oeh.header_id) total_value
,oel.ordered_quantity ordered_quantity
-- Production
, tbl0.qty_completed as qty_completed
,disc.wip_entity_id as wip_entity_id
,( select wip_entity_name from APPS.wip_entities ent
where ent.wip_entity_id = disc.wip_entity_id) job_name
,disc.status_type
,disc.date_released as job_released_date
, DECODE ( disc.date_completed, NULL, disc.date_completed,
to_date(to_char(to_date(TO_CHAR(disc.date_completed-interval '7' hour,'DD-MON-YYYY')||'00:00:00','DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS')) as date_completed
, DECODE ( disc.date_closed, NULL, disc.date_closed,
to_date(to_char(to_date(TO_CHAR(disc.date_closed-interval '7' hour,'DD-MON-YYYY')||'00:00:00','DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS')) as date_closed
, disc.net_quantity
, ( select opr2.quantity_completed
from APPS.wip_operations opr2
where opr2.wip_entity_id = disc.wip_entity_id
and opr2.operation_seq_num = (select max(opr.operation_seq_num)
from APPS.wip_operations opr, APPS.wip_discrete_jobs disc2
where opr.wip_entity_id = disc2.wip_entity_id
and disc2.wip_entity_id = disc.wip_entity_id))* agv.gx_cp_length * agv.gx_cp_th_weight as prod_qty_kgs
,gx_cp_alloy as alloy
,gx_cp_profile_id as profile
-- Theoretical Order cost
,tbl0.TOT_THEORY_COST_RELIEVED
-- Actual Order cost
,tbl0.TOT_ACTUAL_COST_INCURRED
from XX.XXREPORT_Lzero_TBL tbl0
join APPS.oe_order_headers_all oeh on oeh.header_id = tbl0.header_id
join APPS.oe_order_lines_all oel on oeh.org_id = oel.org_id and oeh.header_id = oel.header_id
join APPS.wip_discrete_jobs disc on oel.line_id = disc.source_line_id
join APPS.ego_gx_configured_pr_agv agv on agv.inventory_item_id= oel.inventory_item_id
where oel.link_to_line_id is null
)a
) xx;
There's almost certainly no short and simple solution to tuning this query. The problem here is it's size and complexity. Lack of performance is merely a consequence.
As a first step I would consider taking a break from the keyboard. Grab a pen and paper and in plain English (or whichever "human" language you prefer) write the questions you want answered from your database via this query. Then ask yourself what columns/variables/attributes do you absolutely need to answer those questions? Write them down as well.
Now, do you really need all of those columns, nested joins, selects, and so forth to produce those variables? Maybe, but probably not. The key point here is to focus on only the data/information you need (YAGNI) and from there map out a picture the bare relationships you need to produce the information that answer your question. In other words, work from the outside in, not the other way around.
I realize that this perhaps sounds a bit abstract and vague, but the whole point is that maintaining clear and simple code is always an ongoing struggle. Keeping your eye on the objective at hand will help keep your head of the weeds.
Finally, a few more specific thoughts at a glance: