优化嵌套查询和联接

时间:2019-01-28 15:35:13

标签: sql oracle optimization

我有一个查询,该查询可以通过在单个客户帐户上运行来实现。但是,当我打开它查询所有帐户时,它变得非常慢。我还没有找到可以使我对脚本进行任何改进的帖子。

我将在下面发布脚本。我没有具体的问题,但想知道是否可以进行任何优化改进以提高查询速度?

select 

  count ( distinct abc.OrderNo) as Total_Orders,
  sum (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image'then 1 else 0 end) as Total_DIDs,
  count (distinct  (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image'  then abc.OrderNo end ))  as Total_DID_Orders,
  sum (case when abc.ItemDescription_Detail = 'CD High and Low Resolution'then 1 else 0 end) as Total_CD_Looks,
  count (distinct  (case when abc.ItemDescription_Detail = 'CD High and Low Resolution'  then abc.OrderNo end ))  as Total_CD_Orders, 

  sum (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image' and abc.NORMALPKGFLAG = '1' then 1 else 0 end) as Total_PKG_DIDs,
  count (distinct  (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image' and abc.NORMALPKGFLAG = '1' then abc.OrderNo end ))  as Total_PKG_DID_Orders,
  sum (case when abc.ItemDescription_Detail = 'CD High and Low Resolution' and abc.NORMALPKGFLAG = '1' then 1 else 0 end) as Total_PKG_CD_Looks,
  count (distinct  (case when abc.ItemDescription_Detail = 'CD High and Low Resolution' and abc.NORMALPKGFLAG = '1' then abc.OrderNo end ))  as Total_PKG_CD_Orders, 

  sum (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image' and abc.SPECIALFLAG = '1' then 1 else 0 end) as Total_SPL_OFFER_DIDs,
  count (distinct  (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image' and abc.SPECIALFLAG = '1' then abc.OrderNo end ))  as Total_SPL_OFFER_DID_Orders,
  sum (case when abc.ItemDescription_Detail = 'CD High and Low Resolution' and abc.SPECIALFLAG = '1' then 1 else 0 end) as Total_SPL_OFFER_CD_Looks,
  count (distinct  (case when abc.ItemDescription_Detail = 'CD High and Low Resolution' and abc.SPECIALFLAG = '1' then abc.OrderNo end ))  as Total_SPL_OFFER_CD_Orders, 

  sum (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image' and abc.CREATEPKG = '1' then 1 else 0 end) as Total_CYOP_DIDs,
  count (distinct  (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image' and abc.CREATEPKG = '1' then abc.OrderNo end ))  as Total_CYOP_DID_Orders,
  sum (case when abc.ItemDescription_Detail = 'CD High and Low Resolution' and abc.CREATEPKG = '1' then 1 else 0 end) as Total_CYOP_CD_Looks,
  count (distinct  (case when abc.ItemDescription_Detail = 'CD High and Low Resolution' and abc.CREATEPKG = '1' then abc.OrderNo end ))  as Total_CYOP_CD_Orders, 

  sum (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image' and abc.CREATEPKG <> '1' and abc.SPECIALFLAG <> '1' and abc.NORMALPKGFLAG <> '1' then 1 else 0 end) as Total_Not_PKG_DIDs,
  count (distinct  (case when abc.ItemDescription_Detail = 'Hi-Res Digital Image' and abc.CREATEPKG <> '1' and abc.SPECIALFLAG <> '1' and abc.NORMALPKGFLAG <> '1' then abc.OrderNo end ))  as Total_Not_PKG_DID_Orders,
  sum (case when abc.ItemDescription_Detail = 'CD High and Low Resolution' and abc.CREATEPKG <> '1' and abc.SPECIALFLAG <> '1' and abc.NORMALPKGFLAG <> '1' then 1 else 0 end) as Total_Not_PKG_CD_Looks,
  count (distinct  (case when abc.ItemDescription_Detail = 'CD High and Low Resolution' and abc.CREATEPKG <> '1' and abc.SPECIALFLAG <> '1' and abc.NORMALPKGFLAG <> '1' then abc.OrderNo end ))  as Total_Not_PKG_CD_Orders 

from (select
        distinct
        oh.Event_Ref_ID,
        --oc.CHANNEL_NAME,
        oh.Order_Header_OID OrderHeader,
        oh.Order_No OrderNo,
        oh.Order_Date OrderDate,
        ol.Order_Line_OID OrderLine,
        ol.Unit_Price UnitPrice,
        ol.Ordered_Quantity Qty,
        --ol.List_Price ListPrice,
        --ol.Line_Total LineTotal,
        --ol.Est_Pretax_Amount EstPreTaxAmount,
        ------old.Order_Line_Detail_OID OrderLineDetail,
        ------old.Sheet_Size SheetSize,
        i.SKU_Category,
        i.Description ItemDescription,
        bi.SKU_Category SKUCategory_Detail,
        bi.Description ItemDescription_Detail,
        --ole.LookID,
        --bole.LookID,
        case when i.sku_category = 'PACKAGE' and i.Description  like '%Special%' then 1 else 0 end as SpecialFlag,
        case when i.sku_category = 'PACKAGE' and i.Description  like '%Create%' then 1 else 0 end as CreatePKG,
        case when i.sku_category = 'PACKAGE' and i.Description  not like '%Special%' and i.Description  not like '%Create%' then 1 else 0 end as NormalPKGFlag,
        case when bole.LookID IS NOT NULL  then bole.LookID else ole.LookID end as LookIDV2,
        Round (case when i.sku_category = 'PACKAGE' then ((ol.line_total) / (count(*) over (partition by ol.Order_Line_OID))) else (case when ol.line_total = '0' then ol.List_Price else ol.line_total end)  end, 2) as LINETOTAL,
        Round (case when i.sku_category = 'PACKAGE' then ((ol.Est_Pretax_Amount) / (count(*) over (partition by ol.Order_Line_OID))) else ol.Est_Pretax_Amount end, 2) as EST_PRE_TAX_LINETOTAL
        --count(*) over (partition by ol.Order_Line_OID) TotalinPKG

from (select * from ODS_OWN.ORDER_HEADER oh 
        where 
                EXISTS (select * from ODS_OWN.EVENT e where e.School_Year = 2019 and e.EVENT_REF_ID = oh.EVENT_REF_ID)
                and
                EXISTS (select * from ODS_OWN.ORDER_CHANNEL oc where CHANNEL_NAME = 'MLT' and oh.ORDER_CHANNEL_OID = oc.ORDER_CHANNEL_OID)

        ) oh


--inner join (select distinct ORDER_CHANNEL_OID, CHANNEL_NAME from ODS_OWN.ORDER_CHANNEL where CHANNEL_NAME = 'MLT') oc on oh.ORDER_CHANNEL_OID = oc.ORDER_CHANNEL_OID -- 
inner join ODS_OWN.APO apo on apo.APO_OID = oh.APO_OID
left join ODS_OWN.ORDER_LINE ol on oh.ORDER_HEADER_OID =  ol.ORDER_HEADER_OID
left join ODS_OWN.ORDER_LINE_DETAIL olde on ol.ORDER_LINE_OID = olde.ORDER_LINE_OID
left join ODS_OWN.ITEM i on ol.ITEM_OID = i.ITEM_OID
left join ODS_OWN.ORDER_LINE bol ON (ol.ORDER_LINE_OID = bol.BUNDLE_PARENT_ORDER_LINE_OID)
left join ODS_OWN.ITEM bi ON (bol.ITEM_OID = bi.ITEM_OID)
left join ODS_OWN.ORDER_LINE_DETAIL bold ON (bol.ORDER_LINE_OID = bold.ORDER_LINE_OID)
left join (select 
                ORDER_LINE_DETAIL_OID, 
                SUBSTR(ALIAS_ID,instr(alias_ID,' ')+1,LENGTH(ALIAS_ID)) as LookID
        from ODS_OWN.ORDER_LINE_ELEMENT
        where length(trim(alias_id)) > 0) ole on olde.ORDER_LINE_DETAIL_OID = ole.ORDER_LINE_DETAIL_OID
left join (select 
                ORDER_LINE_DETAIL_OID, 
                SUBSTR(ALIAS_ID,instr(alias_ID,' ')+1,LENGTH(ALIAS_ID)) as LookID
        from ODS_OWN.ORDER_LINE_ELEMENT 
        where length(trim(alias_id)) > 0) bole on bold.ORDER_LINE_DETAIL_OID = bole.ORDER_LINE_DETAIL_OID

where
ol.list_price != 0) abc

1 个答案:

答案 0 :(得分:0)

首先,我将尝试摆脱一些嵌套。

例如:-

(select * from ODS_OWN.ORDER_HEADER oh 
        where 
                EXISTS (select * from ODS_OWN.EVENT e where e.School_Year = 2019 and e.EVENT_REF_ID = oh.EVENT_REF_ID)
                and
                EXISTS (select * from ODS_OWN.ORDER_CHANNEL oc where CHANNEL_NAME = 'MLT' and oh.ORDER_CHANNEL_OID = oc.ORDER_CHANNEL_OID)

        ) oh

可以将其预先运行到临时表或变量表中吗?那么您可以直接引用它,而不必让查询针对每一行运行以获取相同的数据。另外,我会引用列而不是使用*。可能没有其他列,但是命名它们通常更快。

类似地,这两个子查询:-

left join (select 
                ORDER_LINE_DETAIL_OID, 
                SUBSTR(ALIAS_ID,instr(alias_ID,' ')+1,LENGTH(ALIAS_ID)) as LookID
        from ODS_OWN.ORDER_LINE_ELEMENT
        where length(trim(alias_id)) > 0) ole on olde.ORDER_LINE_DETAIL_OID = ole.ORDER_LINE_DETAIL_OID
left join (select 
                ORDER_LINE_DETAIL_OID, 
                SUBSTR(ALIAS_ID,instr(alias_ID,' ')+1,LENGTH(ALIAS_ID)) as LookID
        from ODS_OWN.ORDER_LINE_ELEMENT 
        where length(trim(alias_id)) > 0) bole on bold.ORDER_LINE_DETAIL_OID = bole.ORDER_LINE_DETAIL_OID

在处理字符串操作时可能很昂贵。如果可以将它们再次预运行到临时表,变量表中,甚至可以作为CTE运行,则可能会提高性能。