2014-10-20 45 views
0

我有一個腳本,顯示了幾個製造組件的交付數量數據。每個組件都有不同的新發布日期,因此數據將從不同的開始日期開始運行(最早日期爲2007年7月1日)。Oracle SQL - 創建循環

完整的腳本在下面發佈。我想補充的是腳本...

*腳本文件刪除*

...這顯示了新的發佈日期交付數量的總和爲91天的時間內(3個月) 。我可以每3個月重複一次這個子選擇,但是,隨着時間的推移,我將不得不添加更多的子選擇,以保持數據運行至今。

有沒有一種方法來運行一個循環,以便每隔91天從新版本返回交付的數量?

*腳本文件刪除*


OK ...感謝您的所有建議重:加入的和子查詢。

我修改了腳本中的連接並刪除了許多子查詢(下面的完整腳本)。

我現在的問題可以追溯到在SQL中創建循環。我可以創建一個循環,從每個月的新發布日期(NR_DATE)到當前日期,每月都可以返回總額遞送量,而不是創建數十個子查詢來顯示指定時間段內的遞送量。子查詢將有可能如下所示(然後重複每個需要的時間)...

(select nvl(sum(dp.del_qty),0) from [email protected]_to_cdsuk dh, [email protected]_to_cdsuk dp where dp.dhead_no = dh.dhead_no and dh.d_status = '9' and dp.article_no = '9'||nrb.p_catnr and trunc(dh.actshpdate) > trunc(sysdate - 30)) sum_CDS_delqty_30_days 

我希望我在做一些感覺......如果道歉,我並不清楚。我只寫了幾個月的SQL,並且使用現有的OLD報告教了自己。

感謝

完整劇本

select pd.part_no, 
    pd.catnr, 
    pd.prodtyp, 
    pd.packtyp, 
    pd.description, 
    ip.purchase_type, 
    nvl(pd.fod_idc, 'N'), 
    (select max(acp.qty_free_idc) 
     from oes_fod_match acp 
    where pd.part_no = acp.part_no 
     and acp.type = 'SUP' 
     and acp.cre_dat = (select max(acp1.cre_dat) 
          from oes_fod_match acp1 
          where acp.part_no = acp1.part_no 
          and acp1.qty_free > 0 
          and acp1.type = 'SUP')) qty_free_idc, 
    (select nvl(sum(pl.qty_onhand), 0) 
     from part_loc pl 
    where pl.part_no = pd.part_no 
     and pl.location_type = 'IN' 
     and pl.plant in ('A', 
      'T', 
      'L')) current_stock_at_comp, 
    (select nvl(sum(pl.qty_onhand), 0) 
     from part_loc pl 
    where pl.part_no = pd.part_no 
     and pl.location_type = 'IN' 
     and pl.plant in ('Z', 
      'V')) current_stock_cz_comp, 
    (select nvl(sum(pl.qty_onhand), 0) 
     from part_loc pl 
    where pl.part_no = pd.part_no 
     and pl.location_type = 'IN' 
     and pl.plant in ('W', 
      '2')) current_stock_uk_comp, 
    (select nvl(sum(pl.qty_onhand), 0) 
     from part_loc pl 
    where pl.part_no = pd.part_no 
     and pl.location_type = 'IN') total_stock_comp, 
    (select nvl(max(val_strg1), 0) 
     from sd_domainval dv 
    where dv.val_strg = pd.part_no) min_stock_lvl, 
    (select nvl(max(val_strg2), 0) 
     from sd_domainval dv 
    where dv.val_strg = pd.part_no) min_order_qty, 
    (select nvl(max(val_strg3), 'ND') 
     from sd_domainval dv 
    where dv.val_strg = pd.part_no) pref_assembly_plant, 
    (select nvl(max(pp.qty), 0) 
     from oes_purpos pp 
    where pp.av_part_no = pd.part_no 
     and pp.c_status != 'D' 
     and pp.datneu = (select max(pp1.datneu) 
          from oes_purpos pp1 
         where pp1.av_part_no = pp.av_part_no 
          and pp1.c_status != 'D')) last_aw_po_qty, 
    (select nvl(sum(ps.requ_qty - nvl(ps.del_qty, 0)), 0) 
     from oes_purpos pp, 
      oes_purseg ps 
    where ps.headnr = pp.headnr 
     and ps.posnr = pp.posnr 
     and pp.av_part_no = pd.part_no 
     and ps.c_status not in ('9', 
      'D') 
     and ps.o_status not in ('D', 
      '9')) open_aw_po_qty, 
    (select nvl(sum(al.qty_onhand), 0) 
     from [email protected]_to_cdsuk l, 
      [email protected]_to_cdsuk al 
    where al.article_no = '9' || nrb.p_catnr 
     and al.qty_onhand <> 0 
     and l.location_no = al.location_no 
     and l.location_no like ' 1    DCMS%' 
     and l.location_class not in ('D', 
      'C')) onhand_CDS, 
    (select nvl(sum(st.qty_in_process), 0) 
     from [email protected]_to_cdsuk st 
    where st.article_no = '9' || nrb.p_catnr) allocated_CDS, 
    (select nvl(sum(st.qty_in_process), 0) 
     from [email protected]_to_cdsuk st 
    where st.article_no = '9' || nrb.p_catnr) allocated_CDS, 
    (select min(selection_relse_date) 
     from [email protected]_to_cdsuk st 
    where substr(selection_no, 2, 99) = pd.catnr) NR_DATE, 
    (select sum(ds.planqty - nvl(ds.delqty, 0)) 
     from oes_opos op, 
      oes_oposdelseg ds, 
      ncf_comppart nc, 
      oes_nrbom nb 
    where ds.ordnr = op.ordnr 
     and ds.posnr = op.posnr 
     and nc.item_part_no = pd.part_no 
     and nb.c_catnr = nc.catnr 
     and nb.c_prodtyp = nc.prodtyp 
     and nb.c_packtyp = nc.packtyp 
     and nb.c_vernr = nc.vernr 
     and op.catnr = nb.p_catnr 
     and op.prodtyp = nb.p_prodtyp 
     and op.packtyp = nb.p_packtyp 
     and op.vernr = nb.p_vernr 
     and ds.c_status not in ('9', 
      'D') 
     and op.ol_typ = 'XX') sum_open_xx_order, 
    (select nvl(sum(pl.qty_onhand), 0) 
     from ncf_comppart nc, 
      oes_nrbom nb, 
      part_description pd1, 
      part_loc pl 
    where nc.item_part_no = pd.part_no 
     and nb.c_catnr = nc.catnr 
     and nb.c_prodtyp = nc.prodtyp 
     and nb.c_packtyp = nc.packtyp 
     and nb.c_vernr = nc.vernr 
     and pd1.catnr = nb.p_catnr 
     and pd1.prodtyp = nb.p_prodtyp 
     and pd1.packtyp = nb.p_packtyp 
     and pd1.vernr = nb.p_vernr 
     and pl.part_no = pd1.part_no) onhand_avalon_fp, 
    (select unique sv.gps_planshpdate 
     from oes_delsegview sv, 
      oes_opos op, 
      oes_oposdelseg ds, 
      oes_nrbom nb, 
      ncf_comppart cp 
    where cp.item_part_no = pd.part_no 
     and nb.c_catnr = cp.catnr 
     and nb.c_prodtyp = cp.prodtyp 
     and nb.c_packtyp = cp.packtyp 
     and nb.c_vernr = cp.vernr 
     and sv.ordnr = ds.ordnr 
     and sv.posnr = ds.posnr 
     and sv.catnr = nb.p_catnr 
     and sv.prodtyp = nb.p_prodtyp 
     and sv.packtyp = nb.p_packtyp 
     and op.ordnr = ds.ordnr 
     and op.posnr = ds.posnr 
     and op.catnr = nb.p_catnr 
     and op.prodtyp = nb.p_prodtyp 
     and op.packtyp = nb.p_packtyp 
     and op.vernr = nb.p_vernr 
     and nb.active = 'Y' 
     and op.ol_typ in ('XX', 
      'CO') 
     and sv.gps_planshpdate = (select max(sv1.gps_planshpdate) 
            from oes_delsegview sv1, 
             oes_opos op1, 
             oes_oposdelseg ds1, 
             oes_nrbom nb1, 
             ncf_comppart cp1 
            where cp1.item_part_no = cp.item_part_no 
            and nb1.c_catnr = cp1.catnr 
            and nb1.c_prodtyp = cp1.prodtyp 
            and nb1.c_packtyp = cp1.packtyp 
            and nb1.c_vernr = cp1.vernr 
            and sv1.ordnr = ds1.ordnr 
            and sv1.posnr = ds1.posnr 
            and sv1.catnr = nb1.p_catnr 
            and sv1.prodtyp = nb1.p_prodtyp 
            and sv1.packtyp = nb1.p_packtyp 
            and op1.ordnr = ds1.ordnr 
            and op1.posnr = ds1.posnr 
            and op1.catnr = nb1.p_catnr 
            and op1.prodtyp = nb1.p_prodtyp 
            and op1.packtyp = nb1.p_packtyp 
            and op1.vernr = nb1.p_vernr 
            and nb1.active = 'Y' 
            and sv1.ord_o_status = '9' 
            and op1.ol_typ in ('XX', 
             'CO'))) last_ship_date_manufacturing, 
    (select unique nvl(max(sv.delqty), 0) 
     from oes_delsegview sv, 
      oes_opos op, 
      oes_oposdelseg ds, 
      oes_nrbom nb, 
      ncf_comppart cp 
    where cp.item_part_no = pd.part_no 
     and nb.c_catnr = cp.catnr 
     and nb.c_prodtyp = cp.prodtyp 
     and nb.c_packtyp = cp.packtyp 
     and nb.c_vernr = cp.vernr 
     and sv.ordnr = ds.ordnr 
     and sv.posnr = ds.posnr 
     and sv.catnr = nb.p_catnr 
     and sv.prodtyp = nb.p_prodtyp 
     and sv.packtyp = nb.p_packtyp 
     and op.ordnr = ds.ordnr 
     and op.posnr = ds.posnr 
     and op.catnr = nb.p_catnr 
     and op.prodtyp = nb.p_prodtyp 
     and op.packtyp = nb.p_packtyp 
     and op.vernr = nb.p_vernr 
     and nb.active = 'Y' 
     and op.ol_typ in ('XX', 
      'CO') 
     and sv.gps_planshpdate = (select max(sv1.gps_planshpdate) 
            from oes_delsegview sv1, 
             oes_opos op1, 
             oes_oposdelseg ds1, 
             oes_nrbom nb1, 
             ncf_comppart cp1 
            where cp1.item_part_no = cp.item_part_no 
            and nb1.c_catnr = cp1.catnr 
            and nb1.c_prodtyp = cp1.prodtyp 
            and nb1.c_packtyp = cp1.packtyp 
            and nb1.c_vernr = cp1.vernr 
            and sv1.ordnr = ds1.ordnr 
            and sv1.posnr = ds1.posnr 
            and sv1.catnr = nb1.p_catnr 
            and sv1.prodtyp = nb1.p_prodtyp 
            and sv1.packtyp = nb1.p_packtyp 
            and op1.ordnr = ds1.ordnr 
            and op1.posnr = ds1.posnr 
            and op1.catnr = nb1.p_catnr 
            and op1.prodtyp = nb1.p_prodtyp 
            and op1.packtyp = nb1.p_packtyp 
            and op1.vernr = nb1.p_vernr 
            and nb1.active = 'Y' 
            and sv1.ord_o_status = '9' 
            and op1.ol_typ in ('XX', 
             'CO'))) last_ship_qty_manufacturing, 
    case when case when (select max(psd.conf_date) 
          from oes_purseg psd, 
           OES_PURSEGVIEW psv 
         where psv.headnr = psd.headnr 
          and psv.posnr = psd.posnr 
          and psv.segnr = psd.segnr 
          and psv.av_part_no = pd.part_no 
          and psv.ps_o_status in ('1', '2', '7') 
          and psv.ps_c_status not in ('D', '9')) is null then (select max(psd.requ_date)                      from oes_purseg psd, 
                         OES_PURSEGVIEW psv 
                       where psv.headnr = psd.headnr 
                        and psv.posnr = psd.posnr 
                        and psv.segnr = psd.segnr 
                        and psv.av_part_no = pd.part_no 
                        and psv.ps_o_status in ('0', '1', '2', '7') 
                        and psv.ps_c_status not in ('D', '9')) 
        else (select max(psd.conf_date) 
          from oes_purseg psd, 
           OES_PURSEGVIEW psv 
         where psv.headnr = psd.headnr 
          and psv.posnr = psd.posnr 
          and psv.segnr = psd.segnr 
          and psv.av_part_no = pd.part_no 
          and psv.ps_o_status in ('1', '2', '7') 
          and psv.ps_c_status not in ('D', '9')) end is null then (select max(ps1.del_date) 
                         from oes_purseg ps1 
                        where ps1.headnr || ps1.posnr || ps1.segnr = (select rq.pur_headnr || rq.pur_posnr || rq.pur_segnr 
                                    from oes_requisition rq 
                                    where rq.seqnr = (select fm.req_seqnr 
                                         from oes_fod_match fm 
                                         where fm.part_no = pd.part_no 
                                         and fm.qty_free_idc = 'Y' 
                                         and fm.cre_dat = (select max(fM1.cre_dat) 
                                              from oes_fod_match fm1 
                                              where fm.part_no = fm1.part_no 
                                               and fm1.qty_free_idc = 'Y')))) 
     else case when (select max(psd.conf_date) 
          from oes_purseg psd, 
           OES_PURSEGVIEW psv 
         where psv.headnr = psd.headnr 
          and psv.posnr = psd.posnr 
          and psv.segnr = psd.segnr 
          and psv.av_part_no = pd.part_no 
          and psv.ps_o_status in ('1', '2', '7') 
          and psv.ps_c_status not in ('D', '9')) is null then (select max(psd.requ_date) 
                        from oes_purseg psd, 
                         OES_PURSEGVIEW psv 
                       where psv.headnr = psd.headnr 
                        and psv.posnr = psd.posnr 
                        and psv.segnr = psd.segnr 
                        and psv.av_part_no = pd.part_no 
                        and psv.ps_o_status in ('1', '2', '7') 
                        and psv.ps_c_status not in ('D', '9')) 
        else (select /*+ ORDERED */ max(psd.conf_date) 
          from oes_purseg psd, 
           OES_PURSEGVIEW psv 
         where psv.headnr = psd.headnr 
          and psv.posnr = psd.posnr 
          and psv.segnr = psd.segnr 
          and psv.av_part_no = pd.part_no 
          and psv.ps_o_status in ('1', '2', '7') 
          and psv.ps_c_status not in ('D', '9')) end end ACP_start_date, 
    (select max(acp2.cre_dat) 
     from oes_fod_match acp2 
    where pd.part_no = acp2.part_no 
     and acp2.type = 'SUP' 
     and acp2.cre_usr = 'SOX9347') ACP_migration_date, 
    (select round(nvl(avg(dp.del_qty), 0)) 
     from [email protected]_to_cdsuk dh, 
      [email protected]_to_cdsuk dp 
    where dp.dhead_no = dh.dhead_no 
     and dh.d_status = '9' 
     and dp.article_no = '9' || nrb.p_catnr 
     and dh.actshpdate > sysdate - 365) * 90 avg_CDS_delqty_last_2_mths, 
    nrb.p_catnr used_in_catnr 
    FROM part_description pd 
    INNER JOIN inventory_purchase ip 
     ON ip.part_no = pd.part_no 
    INNER JOIN scm_prodtyp pt 
     ON pt.prodtyp = pd.prodtyp 
    INNER JOIN oes_fod_match acp 
     ON acp.part_no = pd.part_no 
    INNER JOIN part_description pd3 
     ON pd3.part_no = pd.part_no 
    INNER JOIN NCF_COMPPART ncf 
     ON ncf.item_part_no = pd3.part_no 
    INNER JOIN oes_nrbom nrb 
     ON ncf.catnr = nrb.c_catnr 
     AND ncf.prodtyp = nrb.c_prodtyp 
     AND ncf.packtyp = nrb.c_packtyp 
     AND ncf.vernr = nrb.c_vernr 
WHERE pd.cunr in ('649830', 'W30000') 
    and pd.catnr = '2EDVD0017' 
    and pd.fod_idc = 'Y' 
    and pt.prodgrp = 'AW' 
+0

也許你應該把你的腳本放入SQL文件中並使其參數化,並從SQL * Plus的主腳本中調用N次來傳遞新的數字。這不是循環,但至少你不需要複製/粘貼整個查詢。 – Rusty 2014-10-20 08:59:36

+0

你真的想要一個固定的91天期限,而不是三個日曆月?每當你輸掉一天(或閏年中的兩次),你的時間將會不同。一個簡單的示例數據和所需的輸出示例將使您更容易理解併爲您提供幫助。 – 2014-10-20 09:14:41

+0

@SMORF當你完成這個問題時,請打勾接受其中一個答案。 – 2014-10-21 02:07:45

回答

1

我很難決定從哪裏開始,但我還是決定在此:JOINS

我在我看來,如果你嘗試應用ANSI加盟在沒有連接條件的情況下,您在查詢中有一個表,因此您可能有一個笛卡爾積,它只會乘以結果行數。

即試圖從你的原動:

FROM part_description pd 
    , inventory_purchase ip 
    , scm_prodtyp pt 
    , oes_fod_match acp 
    , NCF_COMPPART ncf 
    , part_description pd3 
    , oes_nrbom nrb 
WHERE ip.part_no = pd.part_no 
     AND pt.prodtyp = pd.prodtyp 
     AND pt.prodgrp = 'AW' 
     AND pd.cunr IN ('649830', 'W30000') 
     AND pd.catnr IN ('BBCDVD3285', 'BBCDVD3297', 'BBCDVD2816', '2EDVD0146', 'BBCDVD1020', 'BBCDVD2687', 'BBCDVD1106') 
     AND pd.fod_idc = 'Y' 
     AND ncf.item_part_no = pd3.part_no 
     AND ncf.catnr = nrb.c_catnr 
     AND ncf.prodtyp = nrb.c_prodtyp 
     AND ncf.packtyp = nrb.c_packtyp 
     AND ncf.vernr = nrb.c_vernr 
     AND pd3.part_no = pd.part_no 

一種變體使用顯式聯接語法:

FROM part_description pd 
INNER JOIN inventory_purchase ip ON ip.part_no = pd.part_no 
INNER JOIN scm_prodtyp pt  ON pt.prodtyp = pd.prodtyp 
            AND pt.prodgrp = 'AW' 

CROSS JOIN oes_fod_match acp --<< NO join conditions given 

INNER JOIN part_description pd3 ON pd3.part_no = pd.part_no 
INNER JOIN NCF_COMPPART ncf  ON ncf.item_part_no = pd3.part_no 

INNER JOIN oes_nrbom nrb ON ncf.catnr = nrb.c_catnr 
            AND ncf.prodtyp = nrb.c_prodtyp 
            AND ncf.packtyp = nrb.c_packtyp 
            AND ncf.vernr = nrb.c_vernr 

WHERE pd.cunr IN ('649830', 'W30000') 
     AND pd.catnr IN ('BBCDVD3285', 'BBCDVD3297', 'BBCDVD2816', '2EDVD0146', 'BBCDVD1020', 'BBCDVD2687', 'BBCDVD1106') 
     AND pd.fod_idc = 'Y' 

沒有指定的連接條件的表:oes_fod_match(ACP)

這很可能是對此查詢的性能產生很大的負面影響,這也許就是爲什麼你一開始就使用SELECT UNIQUE的原因。順便說一句,「SELECT UNIQUE」也會讓它變慢。然後通過在許多不必要的行上運行63個相關的子查詢來乘以所有這些。哇!並且你想添加更多的子查詢。

請停下來一會兒,重新考慮一下連接。我可能是錯的,我希望爲你着想,但請確保在添加任何東西之前,oes_fod_match已正確連接。

+0

嗨,非常感謝您的建議。你是對的;我錯過了acp join(acp.part_no = pd.part_no)。現在報告運行速度更快! – SMORF 2014-10-20 10:12:48

+0

現在是您採用明確連接語法的時候了,以這種方式創建一個意外的笛卡兒積是不可能的。將「交叉連接」替換爲「內部連接」,然後按「ON acp.part_no = pd.part_no」進行。然後你有一組有效的連接,並且更容易在where子句中維護。真的,請停止使用「古代的加入方式」(通過where子句)。 – 2014-10-20 12:59:58

0

關於大量「相關子查詢」(63我認爲):

這些通常是不進行查詢的有效途徑,他們常常可以通過更有效的方法來代替。我相信這是這裏的情況。

這裏是爲那些子查詢6的例子(從原來的未經編輯的問題):

(select nvl(sum(ps.requ_qty),0) from oes_purpos pp, oes_purseg ps where ps.headnr = pp.headnr and ps.posnr = pp.posnr and pp.av_part_no = pd.part_no and ps.c_status != 'D' and ps.requ_date > sysdate - 90) sum_aw_po_qty_3_mths, 
    (select nvl(sum(ps.requ_qty),0) from oes_purpos pp, oes_purseg ps where ps.headnr = pp.headnr and ps.posnr = pp.posnr and pp.av_part_no = pd.part_no and ps.c_status != 'D' and ps.requ_date > sysdate - 180) sum_aw_po_qty_6_mths, 
    (select nvl(sum(ps.requ_qty),0) from oes_purpos pp, oes_purseg ps where ps.headnr = pp.headnr and ps.posnr = pp.posnr and pp.av_part_no = pd.part_no and ps.c_status != 'D' and ps.requ_date > sysdate - 270) sum_aw_po_qty_9_mths, 
    (select nvl(sum(ps.requ_qty),0) from oes_purpos pp, oes_purseg ps where ps.headnr = pp.headnr and ps.posnr = pp.posnr and pp.av_part_no = pd.part_no and ps.c_status != 'D' and ps.requ_date > sysdate - 365) sum_aw_po_qty_12_mths, 
    (select nvl(sum(ps.requ_qty),0) from oes_purpos pp, oes_purseg ps where ps.headnr = pp.headnr and ps.posnr = pp.posnr and pp.av_part_no = pd.part_no and ps.c_status != 'D' and ps.requ_date > sysdate - 540) sum_aw_po_qty_18_mths, 
    (select nvl(sum(ps.requ_qty),0) from oes_purpos pp, oes_purseg ps where ps.headnr = pp.headnr and ps.posnr = pp.posnr and pp.av_part_no = pd.part_no and ps.c_status != 'D' and ps.requ_date > sysdate - 730) sum_aw_po_qty_24_mths, 

我相信可以通過更有效的單一的「派生表」像這樣被替換:

... 
FROM part_description pd 
INNER JOIN (
      select 
        pp.av_part_no 
       , SUM(case when ps.requ_date > TRUNC(sysdate) - 90 then requ_qty else 0 end) sum_aw_po_qty_3_mths 
       , SUM(case when ps.requ_date > TRUNC(sysdate) - 180 then requ_qty else 0 end) sum_aw_po_qty_6_mths 
       , SUM(case when ps.requ_date > TRUNC(sysdate) - 270 then requ_qty else 0 end) sum_aw_po_qty_9_mths 
       , SUM(case when ps.requ_date > TRUNC(sysdate) - 365 then requ_qty else 0 end) sum_aw_po_qty_12_mths 
       , SUM(case when ps.requ_date > TRUNC(sysdate) - 540 then requ_qty else 0 end) sum_aw_po_qty_18_mths 
       , SUM(requ_qty)                 sum_aw_po_qty_24_mths 
      from oes_purpos pp 
      inner join oes_purseg ps ON ps.headnr = pp.headnr and ps.posnr = pp.posnr 
      where ps.c_status != 'D' and ps.requ_date > TRUNC(sysdate) - 730 
      group by 
        pp.av_part_no 
      ) pp on pp.av_part_no = pd.part_no 

6次,我們做了一次,而不是加入,掃描和過濾表oes_purpos pp, oes_purseg ps

同樣的邏輯可以將原來的63子查詢


的方式來應用到其他幾個(可能是所有),你應該使用,使SYSDATE的時間成分被忽略TRUNC(SYSDATE)(即所有的日期比較使用午​​夜)

+0

感謝您的建議 – SMORF 2014-10-20 10:34:20