ZPPR017A: VMI Forecast Report BOM MRP

VMI Forecast 报告生成程序解析
本文介绍了一个用于生成VMI(供应商管理库存)预测报告的ABAP程序。该程序通过从不同数据源获取物料需求信息,并利用ALV网格进行数据展示,支持按需导出为文本文件。此外,程序还提供了灵活的参数配置选项,如选择工厂、物料等。
*&---------------------------------------------------------------------*
*& Progarm      :  ZPPR017A                        Author : Jimmy Wong
*& Created      :  14 Mar 2013                     App    : PP
*& Title        :  VMI Forecast Report
*& Description  :  VMI Forecast Report
*&       T457T    AR    OrdRes OrderRes    (per month request qty) production order
*&                BB    SubReq SubcReqmt                           production order 外发
*&                PP    IndReq IndReqmt                            plan order
*&                SB    DepReq DependReq                           plan order\
*& MD05
*&---------------------------------------------------------------------*
*&  Version       Author      Date        description
*&                Jimmy       14 Mar 2013 the first version
*&  the last update time  2013.03.14 18:00
*&---------------------------------------------------------------------*

report  zppr017a no standard page heading.
*&---------------------------------------------------------------------*
* database table
*&---------------------------------------------------------------------*
tables : mara,marc.
data: begin of it_fg occurs 0,
      werks like marc-werks,
      matnr like marc-matnr,
      end of it_fg.
data: it_sub_matnr like it_fg occurs with header line.
data:lv_first type sy-datum,
     lv_last type sy-datum,
     lv_week_f type kweek,
     lv_week_t type kweek.
data: begin of it_field occurs 0,
      index  type i,
      fieldname(10type c,
      fielddesc(40type c,
      end of it_field.
data: begin of itab occurs 0,
      fg_mat type length 40,
      matnr like marc-matnr,
      fg_matnr like marc-matnr,
      werks like marc-werks,
      clabs   like mchb-clabs,  "On Hand qty
      menge_p   like ekpo-menge,  "Production order Qty
      menge   like ekpo-menge,  "On Order Qty
      weeks   type kweek,
      menge_pl  like ekpo-menge,  "Production order Qty
      mfrnr   like mara-mfrnr,  "Order No.
      mfrpn   like mara-mfrpn,  "Manufacturer
      lifnr   like lfa1-lifnr,
      name1   like lfa1-name1,
      end of itab.
data: wa_itab like itab .
data: begin of it_down occurs 0,
          line type length 10000,
end of it_down .
data:lv_string type string.
data:lv_type type string.
types:lv_types type string.
data: gv_file like rlgrap-filename.

field-symbols: <dyn_table> type standard table, "Dynamic internal table name
               <dyn_wa>    type any,            "Field symbol to create work area
               <dyn_field> type any.            "Field symbol to assign values

data: dy_table type ref to data,
      dy_line  type ref to data,
      it_structure type lvc_t_fcat,
      wa_structure type lvc_s_fcat.
define create_stru.
  wa_structure-fieldname &1.
  wa_structure-inttype &2.
  wa_structure-intlen &3.
  wa_structure-datatype =  &4.
  wa_structure-decimals &5.
  append wa_structure to it_structure.
end-of-definition.
type-pools: slis.
data: fc_hier type slis_t_fieldcat_alv,
      wa_hier type slis_fieldcat_alv .
define alv_field.
  clear:wa_hier.
  wa_hier-fieldname &1.
  wa_hier-seltext_m &2.
  wa_hier-seltext_l &3.
  wa_hier-outputlen &4.
  wa_hier-just &5.
  wa_hier-do_sum &6.
  wa_hier-ref_tabname &7 .
  wa_hier-ref_fieldname &8 .
  append wa_hier to fc_hier.
end-of-definition.
define alv_sort.
  clear sort.
  sort-fieldname &1.
  sort-spos      &2.
  sort-up        &3.
  sort-subtot    &4.
  append sort.
end-of-definition.
data: sort     type slis_t_sortinfo_alv with header line.
*----------------------------------------------------------------------*
*  Parameter & Select-Options                                          *
*----------------------------------------------------------------------*
selection-screen begin of block with frame title text-001.
parameters : s_werks like marc-werks obligatory default '8101'.
select-options : s_matnr for mara-matnr.
select-options : s_mat_d for mara-matnr.
select-options : ms_werks for marc-werks no-display.
selection-screen end of block 1.
selection-screen begin of block with frame title text-002.
parameters: p_detail radiobutton group gp1 default 'X',
          p_summ radiobutton group gp1.
selection-screen end of block 2.
selection-screen begin of block with frame title text-003.
parameters: p_txt as checkbox  .
parameters: p_file like rlgrap-filename default 'C:\temp' .
parameters: p_test as checkbox default 'X' .
selection-screen end of block 3.


at selection-screen on value-request for  p_file.
  perform f4_filename using p_file .


*&---------------------------------------------------------------------*
* start of process
*&---------------------------------------------------------------------*
start-of-selection.
  if s_mat_d[] is not initial and s_matnr[] is initial.
    perform get_component_data.
  else.
    perform get_fg_material.
    if it_fg[] is initial.
      message i003(zmm).
      exit.
    endif.
    perform get_bom_data.
  endif.
  if it_sub_matnr[] is initial.
    message i003(zmm).
    exit.
  endif.
  perform create_structure_w.
  perform create_dynamic_table_w.
  if p_txt 'X'.
    perform add_header.
  endif.
  perform get_mrp_data.

  if p_txt 'X'.
    perform get_file using 'ZPPR017A' p_file p_test '.txt' changing  gv_file.
    if p_test 'X'.
      perform download_local tables it_down using gv_file.
    else.
      perform download_server tables  it_down using  gv_file.
    endif.
  else.
    perform dispaly_data.
  endif.

end-of-selection.
*&---------------------------------------------------------------------*
*&      Form  f4_filename
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_FILENAME text
*----------------------------------------------------------------------*
form f4_filename  using    p_filename.
  call function 'F4_FILENAME'
*    EXPORTING
*     PROGRAM_NAME        = SYST-CPROG
*     DYNPRO_NUMBER       = SYST-DYNNR
*     FIELD_NAME          =
    importing
      file_name           p_filename.
endform.                    " F4_FILENAME
*&---------------------------------------------------------------------*
*&      Form  GET_FG_MATERIAL
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form get_fg_material .
  select werks matnr  into table it_fg
    from marc
    where matnr in s_matnr
      and werks s_werks.
endform.                    " GET_FG_MATERIAL
*&---------------------------------------------------------------------*
*&      Form  GET_BOM_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form get_bom_data .
  data: begin of it_stpo occurs 0 .
          include structure stpox.
  data: end of  it_stpo.
  data: wa_stpo like it_stpo occurs with header line.
  data: begin of it_matcat occurs 0 .
          include structure cscmat.
  data: end of it_matcat.
  loop at it_fg.
    call function 'CS_BOM_EXPL_MAT_V2'
      exporting
        capid                 'PP01'
        datuv                 sy-datum
        emeng                 1
        mtnrv                 it_fg-matnr
        mehrs                 'X'
        mmory                 'X'
        werks                 it_fg-werks
        aumgb                 'X'
      tables
        stb                   it_stpo
        matcat                it_matcat
      exceptions
        material_not_found    4
        no_plant_data         8
        no_bom_found          12
        no_suitable_bom_found 16
        alt_not_found         24
        missing_authorization 28
        conversion_error      36.
    if sy-subrc eq 0 .
      if it_stpo[] is not initial.
        loop at it_stpo.
          check it_stpo-postp 'L'.
          check it_stpo-idnrk in s_mat_d[] .
          it_sub_matnr-matnr it_stpo-idnrk.
          it_sub_matnr-werks it_stpo-werks.
          collect it_sub_matnr.
          clear:it_sub_matnr.
        endloop.
      endif.
    endif.
    clear:it_stpo,it_stpo[],it_matcat,it_matcat[].
  endloop.
endform.                    " GET_BOM_DATA
*&---------------------------------------------------------------------*
*&      Form  CREATE_STRUCTURE_W
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form create_structure_w .
  data: l_fname_i type i,
        l_week(2),
        g_week(3),
        l_year(4),
        lv_str type i,
        l_fname type lvc_fname,
        p_date type sy-datum.
  create_stru 'WERKS'  'C' '4' '' '' .
  create_stru 'FG_MATNR'  'C' '20' '' '' .
  create_stru 'MATNR'  'C' '20' '' '' .
  create_stru 'CLABS'  'P' '20' 'DEC' '3' .
  create_stru 'MENGE_P'  'P' '20' 'DEC' '3' .
  create_stru 'MENGE'  'P' '20' 'DEC' '3' .
  create_stru 'MFRPN'  'C' '40' '' '' .
  create_stru 'MFRNR'  'C' '10' '' '' .
  create_stru 'NAME1'   'C' '20' '' '' .
  create_stru 'PAST_DUE'  'P' '20' 'DEC' '3' .

  p_date sy-datum.
  perform get_week using p_date   changing  lv_week_f.
  perform get_first_date_by_week using lv_week_f changing lv_first.
  l_fname_i lv_week_f.
  l_week lv_week_f+4(2).
  l_year lv_week_f+0(4).

  do 52 times.
    lv_str  strlenl_week ).
    if lv_str 1.
      concatenate '0' l_week into g_week.
    else.
      g_week l_week .
    endif.
    concatenate l_year g_week into lv_week_t  .
    l_fname l_fname_i.
    condense l_fname.
    it_field-index it_field-index 1.
    it_field-fieldname l_fname.
    concatenate 'W' l_fname into it_field-fielddesc .
    collect it_field.
    create_stru l_fname  'P' '20' 'DEC' '3' .
    l_week l_week + 1.
    l_fname_i l_fname_i + 1.
    if l_week 53.
      l_year l_year + 1.
      l_week '01'.
      concatenate l_year l_week into l_fname.
      l_fname_i l_fname.
    endif.
  enddo.
  perform get_first_date_by_week using  lv_week_t  changing lv_last.
  lv_last lv_last + 6.

  create_stru 'TOTAL'  'P' '20' 'DEC' '3' .

endform.                    " CREATE_STRUCTURE_W
*&---------------------------------------------------------------------*
*&      Form  create_dynamic_table_w
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
form create_dynamic_table_w .
  call method cl_alv_table_create=>create_dynamic_table
    exporting
      it_fieldcatalog it_structure
    importing
      ep_table        dy_table.

  assign dy_table->to <dyn_table>.    " 用表类型指针 <dyn_table> 指向 数据对象的内容.
  create data dy_line like line of <dyn_table>.
  assign dy_line->to <dyn_wa>.
endform.                    " CREATE_DYNAMIC_TABLE_W
*&---------------------------------------------------------------------*
*&      Form  GET_MRP_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form get_mrp_data .
  data: it_mrp_items like bapi_mrp_items occurs with header line ,
        lv_edelnr like  mdps-del12 ,
        lv_total type  menge_d.
  data: it_mdrq like mdrq occurs with header line.
  data: begin of it_menge occurs 0,
        werks like marc-werks,
        matnr like mara-matnr,
        weeks   type kweek,
        menge   like ekpo-menge,  "On Order Qty
        end of it_menge.
  data:lv_strmatnr type string,
     lv_week type kweek,
     lv_week_c type length 6.
  data: begin of it_mara occurs 0,
        matnr like mara-matnr,
        mfrnr like mara-mfrnr,
        mfrpn like mara-mfrpn,
        end of it_mara.

  data:begin of it_lifnr occurs 0,
        matnr   like mara-matnr,
        werks   like marc-werks,
        lifnr  like lfa1-lifnr,
        name1  like lfa1-name1,
      end of it_lifnr.

  loop at it_sub_matnr.
    clear: itab.
    move-corresponding it_sub_matnr to itab.

    call function 'BAPI_MATERIAL_MRP_LIST'
      exporting
        material         it_sub_matnr-matnr
        plant            it_sub_matnr-werks
        get_item_details 'X'
        get_ind_lines    ' '
      tables
        mrp_items        it_mrp_items.
    if it_mrp_items[] is initial.
      continue.
    endif.
    delete it_mrp_items where avail_date > lv_last "
                        or mrp_element_ind ne 'AR'
                        and mrp_element_ind ne 'BB'
                        and mrp_element_ind ne 'PP'
                        and mrp_element_ind ne 'SB'
                        and mrp_element_ind ne 'WB'
                        and mrp_element_ind ne 'PB'
                        and mrp_element_ind ne 'BE'
                        and mrp_element_ind ne 'LA') .
    loop at it_mrp_items where  rec_reqd_qty ne 0  .
      if it_mrp_items-mrp_element_ind 'WB' or it_mrp_items-mrp_element_ind 'PB' and  it_mrp_items-rec_reqd_qty > 0 .
        itab-clabs it_mrp_items-rec_reqd_qty .
      elseif   it_mrp_items-mrp_element_ind 'BE' or it_mrp_items-mrp_element_ind 'LA' and  it_mrp_items-rec_reqd_qty > 0 .
        itab-menge it_mrp_items-rec_reqd_qty .
      elseif   it_mrp_items-mrp_element_ind 'AR' or it_mrp_items-mrp_element_ind 'BB' ).
        itab-menge_p =  absit_mrp_items-rec_reqd_qty ).
      endif.
    endloop.

    delete it_mrp_items where avail_date > lv_last "
                        or mrp_element_ind ne 'PP'
                        and mrp_element_ind ne 'SB')
                        or rec_reqd_qty eq 0 .
    read table it_mrp_items index 1.
    if sy-subrc ne 0.
      if itab-clabs and itab-menge and itab-menge_p 0.
        continue.
      endif.
      if p_summ 'X'.
        if itab-fg_matnr is not initial.
          itab-fg_matnr itab-fg_matnr+0(8).
        endif.
        concatenate  itab-fg_matnr itab-matnr into itab-fg_mat.
        collect:itab.
      else.
        concatenate  itab-fg_matnr itab-matnr into itab-fg_mat.
        append:itab.
      endif.
    else.
      loop at it_mrp_items.
        clear: lv_week.
        perform get_week using it_mrp_items-avail_date  changing  lv_week .
        if lv_week < lv_week_f.
          lv_week '200001'.
        endif.
        lv_edelnr it_mrp_items-mrp_no.

        call function 'MD_PEGGING_NODIALOG'
          exporting
            edelet                it_mrp_items-mrp_item
            edelkz                it_mrp_items-mrp_element_ind
            edelnr                lv_edelnr
            edelps                it_mrp_items-mrp_pos
            eplscn                000
            ematnr                it_sub_matnr-matnr
            ewerks                it_sub_matnr-werks
            eplwrk                ' '
            eplaab                it_mrp_items-plngsegmt
            eplanr                it_mrp_items-plngsegno
            eberid                ' '
            edat00                it_mrp_items-avail_date
          tables
*           EMDPSX                =
            imdrqx                it_mdrq
          exceptions
            error                 1
            no_requirements_found 2
            order_not_found       3
            others                4.
        if sy-subrc eq 0.
          if it_mdrq[] is not  initial.
            sort it_mdrq by  werks matnr.
            loop at it_mdrq.
              it_menge-werks it_mdrq-werks.
              it_menge-matnr it_mdrq-matnr.
              it_menge-weeks lv_week .
              it_menge-menge it_mdrq-mng02.
              collect it_menge.
            endloop.
          endif.
        else.
          it_menge-werks it_sub_matnr-werks.
          it_menge-weeks lv_week .
          it_menge-menge absit_mrp_items-rec_reqd_qty ).
          collect it_menge.
        endif.
        clear: it_mdrq,it_mdrq[].
      endloop.
      loop at it_menge.
        itab-menge_pl it_menge-menge.
        itab-fg_matnr it_menge-matnr.
        itab-weeks it_menge-weeks.
        if p_summ 'X'.
          if itab-fg_matnr is not initial.
            itab-fg_matnr itab-fg_matnr+0(8).
          endif.
          concatenate  itab-fg_matnr itab-matnr into itab-fg_mat.
          collect:itab.
        else.
          concatenate  itab-fg_matnr itab-matnr into itab-fg_mat.
          append:itab.
        endif.
      endloop.
      clear: it_menge,it_menge[].
    endif.
    clear:it_mrp_items,it_mrp_items[],itab.
  endloop.

  check itab[] is not initial.

  sort it_sub_matnr by werks matnr.
  select matnr mfrnr mfrpn into table it_mara
      from mara
      for all entries in itab
      where matnr itab-matnr.
  sort it_mara by matnr.

  select  a~matnr a~werks a~lifnr b~name1
    into corresponding fields of table it_lifnr
      from eord as a inner join lfa1 as on a~lifnr b~lifnr
      for all entries in itab
      where a~matnr itab-matnr
        and a~werks itab-werks
        and a~autet '1'.
  sort it_lifnr by werks  matnr.


  sort itab by werks fg_matnr fg_mat .
  loop at itab.
    read table it_mara with  key  matnr itab-matnr binary search.
    if sy-subrc eq 0.
      itab-mfrnr it_mara-mfrnr.
      itab-mfrpn it_mara-mfrpn .
    endif.

    "vendor vendor name
    read table it_lifnr with key werks itab-werks matnr itab-matnr.
    if sy-subrc eq 0.
      itab-lifnr it_lifnr-lifnr.
      itab-name1 it_lifnr-name1.
    endif.
    wa_itab itab.

    if itab-weeks < lv_week_f.
      assign component 'PAST_DUE' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> <dyn_field> +  itab-menge_pl .
    else.
      lv_week_c =  itab-weeks .
      assign component lv_week_c of structure <dyn_wa> to <dyn_field>.
      <dyn_field> <dyn_field> +  itab-menge_pl .
    endif.
    lv_total lv_total + itab-menge_pl .

    at end of fg_mat.
      assign component 'WERKS' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> =  wa_itab-werks.

      assign component 'FG_MATNR' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> wa_itab-fg_matnr.

      assign component 'MATNR' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> wa_itab-matnr.

*    " On hand qty = mmbe Unrestricted use
      assign component 'CLABS' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> wa_itab-clabs.

*    "PO qty  = mmbe On Order
      assign component 'MENGE' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> wa_itab-menge_p.

      assign component 'TOTAL' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> =  lv_total.

      assign component 'MFRPN' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> wa_itab-mfrpn.

      assign component 'MFRNR' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> wa_itab-mfrnr.

      assign component 'NAME1' of structure <dyn_wa> to <dyn_field>.
      <dyn_field> wa_itab-name1.

      if p_txt 'X'.
        loop at it_structure into wa_structure.
          assign component wa_structure-fieldname of structure <dyn_wa> to <dyn_field>.
          if wa_structure-fieldname 'MATNR' or wa_structure-fieldname 'FG_MATNR'.
            perform tranfer_material   using <dyn_field> 'X' changing lv_type.
          else.
            lv_type <dyn_field>.
          endif.
          perform get_string using lv_type changing lv_string.
        endloop.
        it_down-line lv_string.
        condense it_down .
        append it_down .
      endif.

      append <dyn_wa> to <dyn_table>.
      clear: <dyn_wa>,lv_total,lv_string.
    endat.
    clear:wa_itab.
  endloop.
  free:itab,it_mrp_items,it_menge,it_mara,it_lifnr,it_sub_matnr,it_fg.
endform.                    " GET_MRP_DATA
*&---------------------------------------------------------------------*
*&      Form  DISPALY_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form dispaly_data .
  refresh: fc_hier.
  alv_field  'WERKS' 'Plant' '' '6' 'L' '' '' ''.
  alv_field  'FG_MATNR' 'FG Material' '' '18' 'L' '' 'MARA' 'MATNR'.
  alv_field  'MATNR' 'Material' '' '18' 'L' '' 'MARA' 'MATNR'.
  alv_field  'CLABS' '' 'On Hand Qty' '15' 'R' '' '' ''.
  alv_field  'MENGE_P' '' 'Prod Order Qty' '15' 'R' '' '' ''.
  alv_field  'MENGE' '' 'PO Qty' '15' 'R' '' '' ''.
  alv_field  'MFRPN' '' 'Order No.' '' 'L' '' '' ''.
  alv_field  'MFRNR' '' 'Manufacturer' '' 'L' '' '' ''.
  alv_field  'NAME1' '' 'Vendor Name' '20' 'L' '' '' ''.
  alv_field  'PAST_DUE' '' 'Past due' '15' 'R' '' '' ''.
  loop at it_field.
    alv_field  it_field-fieldname it_field-fielddesc '' '12' 'R' '' '' ''.
  endloop.
  alv_field  'TOTAL' '' 'TOTAL' '15' 'R' '' '' ''.

*---SORT
  alv_sort 'WERKS' '1' 'X' 'X' .
  alv_sort 'FG_MATNR' '2' 'X' 'X' .
  alv_sort 'MATNR' '3' 'X' 'X' .

  perform display_alv tables  fc_hier <dyn_table> sort using 'A'.

endform.                    " DISPALY_DATA
*&---------------------------------------------------------------------*
*&      Form  display_alv
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->FC_HIER    text
*      -->ITAB       text
*      -->P_SAVE     text
*----------------------------------------------------------------------*
form display_alv tables fc_hier itab sort
                  using p_save .
  call function 'REUSE_ALV_GRID_DISPLAY'
    exporting
      it_fieldcat        fc_hier[]
      i_save             p_save
      i_callback_program sy-repid
      it_sort            sort[]
    tables
      t_outtab           itab[]
    exceptions
      program_error      1
      others             2.
endform.                    "display_alv
*&---------------------------------------------------------------------*
*&      Form  get_file
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_FILENAME text
*      -->P_FILE     text
*      -->P_TEST     text
*      -->GV_FILE    text
*----------------------------------------------------------------------*
form get_file using p_filename p_file p_test p_ext
              changing gv_file .
  data: wa_key(30type c.
  data: lv_i type i.
  data: lv_c(1type c.
  data: wa_date(8type c.
  data: wa_time like sy-uzeit.
  data: lv_char type c.
  wa_date sy-datum.
  wa_time =  sy-uzeit.
  concatenate p_filename wa_date wa_time  into wa_key.
  concatenate wa_key p_ext  into wa_key. "'.txt'

  lv_i strlenp_file ).
  lv_i lv_i 1 .
  if lv_i > 1.
    lv_c p_file+lv_i(1).
  endif.
  if p_test 'X'.
    lv_char '\' .
  else.
    lv_char '/' .
  endif.
  if lv_c eq lv_char.
    concatenate p_file wa_key into gv_file.
  else.
    concatenate p_file lv_char wa_key into gv_file.
  endif.
endform.  "  get_file
*&---------------------------------------------------------------------*
*&      Form  download_local
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->GV_FILE    text
*----------------------------------------------------------------------*
form download_local  tables it_down
                     using  gv_file .
  data: lv_filename type string.
  lv_filename gv_file.

  call function 'GUI_DOWNLOAD'
    exporting
      filename                lv_filename
      filetype                'ASC'
      write_field_separator   'X'
    tables
      data_tab                it_down
    exceptions
      file_write_error        1
      no_batch                2
      gui_refuse_filetransfer 3
      invalid_type            4
      no_authority            5
      unknown_error           6
      header_not_allowed      7
      separator_not_allowed   8
      filesize_not_allowed    9
      header_too_long         10
      dp_error_create         11
      dp_error_send           12
      dp_error_write          13
      unknown_dp_error        14
      access_denied           15
      dp_out_of_memory        16
      disk_full               17
      dp_timeout              18
      file_not_found          19
      dataprovider_exception  20
      control_flush_error     21
      others                  22.
  if sy-subrc <> 0.
    message id sy-msgid type sy-msgty number sy-msgno
          with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  endif.
endform.                    " DOWNLOAD_LOCAL

*&---------------------------------------------------------------------*
*&      Form  get_first_date_by_week
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_WEEK     text
*      -->P_DATE     text
*----------------------------------------------------------------------*
form get_first_date_by_week using p_week
                            changing p_date .
  call function 'HRIQ_WEEK_GET_FIRST_DAY'
    exporting
      week         p_week
    importing
      date         p_date
    exceptions
      week_invalid 1
      others       2.
endform.                    "get_first_date_by_week
*&---------------------------------------------------------------------*
*&      Form  get_week
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_DATE     text
*      -->P_WEEK     text
*----------------------------------------------------------------------*
form get_week using p_date
              changing p_week.
  call function 'GET_WEEK_INFO_BASED_ON_DATE'
    exporting
      date   p_date
    importing
      week   p_week
*     monday =
*     sunday =
    .
endform.                    "get_week
*&---------------------------------------------------------------------*
*&      Form  GET_STRING
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LV_TYPE  text
*      <--P_LV_STRING  text
*----------------------------------------------------------------------*
form get_string  using    p_type type lv_types
                 changing p_string.
  shift p_type right deleting trailing space.
  shift p_type left deleting leading space.
  if p_string is initial.
    p_string p_type.
  else.
    concatenate p_string
           p_type
          into p_string separated by cl_abap_char_utilities=>horizontal_tab.
  endif.
  condense p_string.
endform.                    " GET_STRING
*&---------------------------------------------------------------------*
*&      Form  tranfer_material
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_OLD      text
*      -->P_OUTPUT   text
*      -->P_NEW      text
*----------------------------------------------------------------------*
form  tranfer_material using    p_old
                                p_output
                       changing p_new  .
  if p_output 'X'.
    call function 'CONVERSION_EXIT_MATN1_OUTPUT'
      exporting
        input  p_old
      importing
        output p_new.
  else.
    data:lv_input type length 50.
    lv_input p_old.
    translate   lv_input to upper case.
    call function 'CONVERSION_EXIT_MATN1_INPUT'
      exporting
        input        lv_input
      importing
        output       p_new
      exceptions
        length_error 1
        others       2.
    if sy-subrc <> 0.
    endif.
  endif.
endform.                    "tranfer_material
*&---------------------------------------------------------------------*
*&      Form  download_server
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->IT_DOWN    text
*      -->GV_FILE    text
*----------------------------------------------------------------------*
form download_server tables lt_down
                    using  gv_file .
  data: begin of it_down occurs 0,
        line type length 10000,
  end of it_down .
  it_down[] lt_down[].
  open dataset gv_file for output in text mode encoding default.
  loop at it_down.
    transfer it_down-line to gv_file.
  endloop.
  close dataset gv_file.
endform.                    " DOWNLOAD_SERVER
*&---------------------------------------------------------------------*
*&      Form  ADD_HEADER
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form add_header .
  perform get_string using 'Plant' changing lv_string.
  perform get_string using 'FG Material' changing lv_string.
  perform get_string using 'Material' changing lv_string.
  perform get_string using 'On Hand Qty' changing lv_string.
  perform get_string using 'Prod Order Qty' changing lv_string.
  perform get_string using 'On Order Qty' changing lv_string.
  perform get_string using 'Order No' changing lv_string.
  perform get_string using 'Manufacturer' changing lv_string.
  perform get_string using 'Vendor Name' changing lv_string.
  perform get_string using 'Past due' changing lv_string.
  loop at it_field.
    lv_type it_field-fielddesc .
    perform get_string using lv_type  changing lv_string.
  endloop.
  perform get_string using 'Total' changing lv_string.

  it_down-line lv_string.
  condense it_down .
  append it_down .
  clear:it_down ,lv_string.
endform.                    " ADD_HEADER
*&---------------------------------------------------------------------*
*&      Form  GET_COMPONENT_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form get_component_data .
  select  werks matnr
      into table it_sub_matnr
    from marc
    where matnr  in s_mat_d
      and werks  s_werks.
endform.                    " GET_COMPONENT_DATA
<think> 我们有一个查询,它返回两个字段:purchaseOrderNo和itemNo。现在,我们有一个输入参数orderNo,需要判断这个orderNo是否等于purchaseOrderNo或者itemNo(注意:itemNo是经过正则替换去掉了前导零的)。如果存在(即orderNo等于purchaseOrderNo或者等于itemNo),则返回1,否则返回0。 但是,注意这里的需求是:根据传入的orderNo,判断在查询结果中是否存在至少一行满足orderNo等于purchaseOrderNo或者等于itemNo。如果存在任何一行满足,就返回1,否则返回0。 然而,这里有一个问题:原查询返回的是多行数据(整个表的数据),而我们只需要根据传入的一个orderNo来检查它是否在任意一行的purchaseOrderNo或itemNo中出现过。 因此,我们需要做的是: 1. 从原表中查询出两个字段:purchaseOrderNo和itemNo(注意itemNo已经去掉了前导零)。 2. 然后,我们使用传入的orderNo(假设我们用变量表示,在Hive中可以用${hivevar:orderNo}的方式)去匹配这两个字段。 但是,我们不需要返回所有的行,而是返回一个标志(0或1)表示是否存在。 我们可以这样写: 思路:使用LEFT SEMI JOIN或者EXISTS,但是Hive中支持EXISTS子查询(但需要注意,Hive的EXISTS子查询要求是相关子查询,且通常用在WHERE子句中)。这里我们可以用另一种方式:使用聚合函数,判断是否有满足条件的行,然后返回0或1。 具体步骤: 1. 我们首先将原表的数据进行转换,得到purchaseOrderNo和itemNo(去掉前导零的采购订单行号)。 2. 然后,我们使用条件过滤:where purchaseOrderNo = ${hivevar:orderNo} or itemNo = ${hivevar:orderNo} 3. 如果存在至少一行,则返回1,否则返回0。 因此,我们可以这样写: ```sql SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS existFlag FROM ods.ods_TOEDP_ZPPR0030_EBELN_d WHERE -- 注意:这里我们使用原始字段进行条件判断,但是要注意itemNo在条件中需要去掉前导零再比较 -- 或者我们可以在子查询中先计算itemNo,然后在外面比较 -- 为了避免重复计算,我们可以使用子查询 purchaseOrderNo = ${hivevar:orderNo} OR regexp_replace(采购订单行号, '^0+', '') = ${hivevar:orderNo} ``` 但是,这里有一个问题:我们无法直接使用别名itemNo在WHERE子句中,所以我们可以写成子查询: ```sql SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS existFlag FROM ( SELECT 采购订单号 as purchaseOrderNo, regexp_replace(采购订单行号, '^0+', '') as itemNo FROM ods.ods_TOEDP_ZPPR0030_EBELN_d ) t WHERE t.purchaseOrderNo = ${hivevar:orderNo} OR t.itemNo = ${hivevar:orderNo} ``` 但是,这个查询会扫描整个表,然后计算两个字段,然后进行过滤。如果表很大,效率可能不高。我们可以考虑在子查询内部就进行条件过滤,但是这里我们不知道传入的orderNo是采购订单号还是采购订单行号(去掉前导零),所以无法提前过滤。 另一种写法,避免子查询: ```sql SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS existFlag FROM ods.ods_TOEDP_ZPPR0030_EBELN_d WHERE 采购订单号 = ${hivevar:orderNo} OR regexp_replace(采购订单行号, '^0+', '') = ${hivevar:orderNo} ``` 这个写法直接使用原始字段,在WHERE条件中,对每一行计算regexp_replace(采购订单行号, '^0+', ''),然后与orderNo比较。这样写简洁,但是要注意正则替换可能会对每一行都执行,如果数据量大,可能会比较慢。 优化:如果采购订单号等于orderNo,那么这一行就满足条件,不需要再计算正则替换。所以,我们可以利用OR条件的短路特性(但Hive中可能不会短路,而是两个条件都计算),所以我们可以考虑分开写,但是Hive中并没有短路保证。因此,我们可以尝试用两个条件分别过滤,然后合并,但是这里用OR就可以。 另外,我们也可以考虑使用UNION ALL来分别匹配两个字段,但是这样可能会扫描两遍表,而且还要去重,所以不推荐。 所以,我们采用第二种直接的方法。 但是,注意:我们传入的orderNo可能是采购订单号,也可能是采购订单行号(去掉前导零后的)。所以,我们这样比较是合理的。 另外,我们只需要知道是否存在,所以用COUNT(1)然后判断是否大于0,然后返回1或0。 但是,如果表非常大,而满足条件的行很少,我们可以加上LIMIT 1来优化吗?但是这里我们用了聚合函数COUNT,所以不能直接加LIMIT。我们可以改写为: ```sql SELECT CASE WHEN EXISTS ( SELECT 1 FROM ods.ods_TOEDP_ZPPR0030_EBELN_d WHERE 采购订单号 = ${hivevar:orderNo} OR regexp_replace(采购订单行号, '^0+', '') = ${hivevar:orderNo} LIMIT 1 ) THEN 1 ELSE 0 END ``` 但是,Hive不支持在EXISTS子句中使用LIMIT(在Hive 2.3.0之前不支持,之后的版本可能支持,但需要确认)。而且,Hive的EXISTS子查询通常需要关联条件,这里我们是非关联的。 所以,为了兼容性,我们使用COUNT的方式,但是我们可以通过设置Hive的优化器参数来减少数据量(比如启用谓词下推等)。另外,我们也可以使用LEFT SEMI JOIN,但是这里只有一个表,所以没必要。 因此,我们最终采用COUNT的方式,但是注意,这样会扫描整个表吗?实际上,如果我们在“采购订单号”和“采购订单行号”上有索引,但Hive没有索引,所以只能全表扫描。但是,如果表很大,我们可以考虑分区表,然后利用分区字段进行过滤,但这里没有提供分区信息。 所以,如果表很大,我们可以考虑使用分页或者采样,但是这样就不准确了。因此,我们假设表不会太大,或者用户能接受全表扫描。 另外,我们还可以考虑使用两个查询分别判断,然后用OR连接,这样可以利用两个字段的单独条件,但是Hive中也没有位图索引,所以效果可能差不多。 综上所述,我们采用以下SQL: ```sql SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS existFlag FROM ods.ods_TOEDP_ZPPR0030_EBELN_d WHERE 采购订单号 = ${hivevar:orderNo} OR regexp_replace(采购订单行号, '^0+', '') = ${hivevar:orderNo} ``` 但是,这里有一个潜在问题:如果orderNo同时匹配了多个行,COUNT(1)会大于0,我们只关心是否存在,所以这样写是没问题的。 另外,注意:正则表达式'^0+'表示去掉开头的一个或多个0。但是,如果采购订单行号全部是0,那么替换后会变成空字符串。所以,如果传入的orderNo是空字符串,那么就会匹配到这些行。不过,通常订单号不会是空字符串,所以需要根据业务确认。 另外,我们也可以考虑在子查询中先去掉前导零,然后进行匹配,这样在子查询中可以看到itemNo字段,更清晰。 因此,我们也可以这样写(两种方式等价): ```sql SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS existFlag FROM ( SELECT 采购订单号, regexp_replace(采购订单行号, '^0+', '') AS itemNo FROM ods.ods_TOEDP_ZPPR0030_EBELN_d ) t WHERE t.采购订单号 = ${hivevar:orderNo} OR t.itemNo = ${hivevar:orderNo} ``` 注意:在子查询中,我们给去零后的采购订单行号起了别名itemNo,然后在外部查询中使用。 两种写法都可以,第一种更简洁,第二种更易读。 我们选择第二种。 但是,这里有一个细节:原表字段名是中文,在子查询中我们使用了别名,但是在外部查询中,我们使用了t.采购订单号(原字段名)和t.itemNo(别名)。注意,在Hive中,字段名是大小写不敏感的,但是中文字段名需要用反引号吗?一般情况下,如果字段名是中文,直接使用即可,但是为了避免问题,最好使用反引号(特别是当字段名有特殊字符时)。不过,这里字段名是中文,且没有特殊字符,所以可以不用。 所以,最终的SQL如下: 假设我们使用Hive变量orderNo,那么在Hive CLI中,我们可以这样设置: set hivevar:orderNo='123456'; 然后执行: ```sql SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS existFlag FROM ( SELECT 采购订单号, regexp_replace(采购订单行号, '^0+', '') AS itemNo FROM ods.ods_TOEDP_ZPPR0030_EBELN_d ) t WHERE t.采购订单号 = '${hivevar:orderNo}' OR t.itemNo = '${hivevar:orderNo}' ``` 注意:我们假设orderNo是字符串,所以用单引号括起来。如果orderNo是数字,也可以不加引号,但为了通用性,建议作为字符串处理。 另外,如果采购订单号或采购订单行号有NULL值,那么条件会忽略NULL(因为NULL与任何值比较都是NULL,相当于false)。所以,如果orderNo不为空,那么NULL不会匹配,这符合逻辑。 因此,这个查询可以满足需求。 但是,我们还要考虑性能:如果表很大,这个查询会扫描全表,然后对每一行都计算正则表达式。我们可以尝试在子查询中提前过滤一部分吗?比如,如果采购订单号等于orderNo,那么就不需要计算正则表达式?但是,在子查询中,我们必须对每一行都计算正则表达式,因为我们要生成itemNo。所以,我们无法避免。 另一种优化:将OR条件拆分成两个条件,分别进行查询,然后取并集。这样,如果第一个条件已经匹配,就不需要再计算第二个条件?但是,在SQL中,OR条件通常会被优化。我们可以写成两个查询然后UNION ALL,但是这样会扫描两遍表,所以不推荐。 所以,我们接受这个查询。 总结:我们使用子查询生成两个字段,然后判断传入的orderNo是否匹配这两个字段中的任意一个,然后统计行数,如果大于0返回1,否则返回0。 注意:这个查询返回一行一列(0或1)。 如果我们需要在程序中调用,那么就可以取这个结果。 但是,如果表是分区表,我们可以在WHERE子句中加入分区过滤,以缩小扫描范围。例如,如果按照日期分区,我们可以加上分区条件。 由于我们不知道具体的分区字段,所以这里没有加。 所以,最终的答案是: </think> 在 Hive 中根据入参 `orderNo` 判断字段是否存在,可以使用以下 SQL 写法: ```sql SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS existsFlag FROM ( SELECT 采购订单号 AS purchaseOrderNo, regexp_replace(采购订单行号, '^0+', '') AS itemNo FROM ods.ods_TOEDP_ZPPR0030_EBELN_d ) t WHERE t.purchaseOrderNo = '${hivevar:orderNo}' OR t.itemNo = '${hivevar:orderNo}' ``` ### 关键说明: 1. **逻辑实现**: - 使用子查询生成 `purchaseOrderNo` 和 `itemNo` 字段 - 通过 `WHERE` 条件匹配入参 `orderNo` - 使用 `COUNT(*)` 统计匹配行数 - `CASE WHEN` 将结果转换为 `1`(存在)或 `0`(不存在) 2. **参数传递**: - 执行前需设置 Hive 变量: ```sql SET hivevar:orderNo='your_order_no'; ``` - 在 SQL 中通过 `${hivevar:orderNo}` 引用变量 3. **执行结果**: - 返回单列 `existsFlag`,值为 `0` 或 `1` - 示例结果: ``` +------------+ | existsFlag | +------------+ | 1 | +------------+ ``` 4. **性能优化**: - 对大数据量表,建议添加分区过滤: ```sql WHERE (t.purchaseOrderNo = '${hivevar:orderNo}' OR t.itemNo = '${hivevar:orderNo}') AND dt = '2023-10-01' -- 分区字段示例 ``` - 可在子查询内部提前过滤: ```sql SELECT ... FROM ... WHERE 采购订单号 = '${hivevar:orderNo}' OR 采购订单行号 LIKE '${hivevar:orderNo}%' ``` ### 替代写法(使用 EXISTS): ```sql SELECT CASE WHEN EXISTS ( SELECT 1 FROM ods.ods_TOEDP_ZPPR0030_EBELN_d WHERE 采购订单号 = '${hivevar:orderNo}' OR regexp_replace(采购订单行号, '^0+', '') = '${hivevar:orderNo}' ) THEN 1 ELSE 0 END AS existsFlag ``` > **注意**:在 Hive 2.3.0+ 版本推荐使用 `EXISTS` 语法,效率更高且可读性更好[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值