2014-10-20 63 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