ABAP - 6 终于来到内表

为了不在数据库表上直接操作。
我们在内存里建了个表,然后把数据库表的数据复制过来。这些内表,我们可以用来做关联啥的。
有些时候我去内表找数据,需要遍历。

我们来抽丝剥茧。这个遍历是个啥啊。。。是一行一行的找么。
我今天突然觉得这个take place这个词组很有意思,拿一个空间来。这个事情就能发生,举行。

我要干啥事,我得有地方来干。得take一个place。

跟计算机讲,我要干什么干什么,前提是我的东西得有地方放。在什么时候放,我都得事无巨细的告诉它。
我要用数据库的表了。
我得先声明 tables: vbap.
然后我这个咋操作呢,我如果就只要用它一个表里的内容,那我就先建一个结构。结构里有一些type的字段。这是个二维的表框框。然后我要take place。要一个type table of的内表空间,还要个work area。
2021.11.24回头看,写的啥玩意*
新写的有了更深的理解:
内表.

好了,然后我把需要的字段从数据库表select出来,into我自己的新建的内表。
条件是啥呢?根据啥来选呢?就where,满足我参数或者select options条件的。

好了,我数据都有了。
接下来进行操作了。

对表中的数值进行合计

这个place有了。给你个地盘了。
接下来呢,还得一步步的告诉计算机。到底啥时候干啥事。

如果我要对表中列里面的值进行合计。
比如说我有物料编号,我需要统计不同物料的价值。
那物料编号,必然的,有很多个。

SORT

我一步步的,我得先把这个物料编号排下序。
那么现在我就来把这个表SORT一下。
SORT it_vbap BY matnr.
于是,所有一个物料编号的,会从上排到下。
在这个内表里。

接下来,干啥呢?
当这些物料编号一样的,我就统计它的value值啊。
这个表里我只有一个可以合并的value值。
那我怎么来统计呢?
我得告诉计算机,啥时候开始计算。

那么event得来上场,因为我需要event来触发。
到了什么event了,然后来触发什么事情。
所有这些操作由于是在表里一行一行的弄。
所以我们需要先把表loop到工作区间里。

LOOP

SORT完了这个表,然后我们把表的行一行一行的loop进到work area里面去。
loop at it_vbap into wa_vbap.

AT FIRST

开始启用这个event,意思是在对表行进行操作之前,要做啥。
做啥呢?要输出表头啊。
于是 AT FIRST.
WRITE : /‘material’ color 2, 12 ‘value’ color 30.
ENDAT.
以上,只是展示了一个表头。
就是告诉它,在表行开头,干啥。

AT END OF

那么还有一个event,at end of 一个字段。
是啥意思呢?
就是我如果有很多个行的值是一样的,到下一行不一样了。
就是这个一样的值end了。
那我可以从这里来进行一个sum.
AT END OF matnr.
sum.
WIRTE: / wa_vbap- matnr color 3 ,wa_vbap-value color 5.
ENDAT.

SUM就是去总计可以加的值类型。你C类型的,它就不加了。
你想显示什么,就可以只显示什么。
如果你只想显示一个统计值。那么就可以只显示一个统计值。

可以在AT END OF 之前,write所有要展示的,这样会形成一个独立的一行累加值。
最后ENDLOOP.

好了,也就是我在一个循环中,对每行的数据at first 和 at end of field进行了一些事件触发,以及做了一些操作。
现在,我想让相同的行编号值隐身,怎么弄呢?
那就是还要有另外一个事件来触发。

这时,怎么实现这种功能呢?怎么压缩它以下的这些相同的列呢?
就是说,当我是一个新的行,那你可以展示其余的列值,当我是个重复的行编号,那可以压缩我,不展示我。

AT NEW

展示不展示我,取决于我是不是一个新行值。
这里还得借助一个event,就是at new。
AT NEW vbeln.
当我这个编号是新的。
我展示我所有的列值。就是write所有的列值。
当我的编号不是新的,怎么办呢?
我就不展示了,是的。我只展示其余的列值。

可是这个是个event啊。它不是个可以判断的值啊。我需要判断它是不是个新值。
我需要给它附加个附庸。

我需要来定义一个变量,data new_po type c.

我需要让它成为可判断是否为新行的at new,于是在AT NEW这个event下面,我们直接来定义一个值。
AT NEW VBELN.
NEW_po = ‘x’.
ENDAT.
那么现在怎么来做判断?
当然是IF
IF new_po = ‘x’.
write: / ****
new_po = ’ '. (同时给这个变量赋值成空。)
ENDIF.

IF new_po = ’ '.
WRITE: / **.
ENDIF.

这个事件会一直执行,到下个事件出现为止。下个事件就是at end of vbeln.

回到这里,会发现有个错误。
就是,当你去查找一个新的行,那么,这个行,设置了一个flag是X。于是我输出第一行,然后我就把这行上的这个flag给设置成空。然后这个空会立刻又执行,于是我下一个if,又会把这行再执行一遍。
就等于第一行,我执行了两遍。
然后我会一直执行下去直到新的行。

这就不行了。
我不需要第一行执行两遍。怎么让它不执行两遍?
首先你得直到它为什么执行了两遍。
因为。我第一行先赋值了X,于是我接下来输出第一行。
然后我赋值了空,我得到第二行再继续输出。可是下面的IF,又满足了,我会持续输出第一行。
这个需要debug。
所以我输出两遍。
那么,我来改下:

IF new_po = ‘x’.
write: / ****
new_po = ’ '. (同时给这个变量赋值成空。)
ELSE.
new_po = ’ '.
WRITE: / **. (这一句不会被执行,因为条件会直接被筛选进第一个if,不会进入这个else)
ENDIF.

adjecent duplicates

毗连重复
我要删除掉一行的重复值。首先排序。
delete adjecent duplicates from it_vbap.

TABLES : vbap.

SELECT-OPTIONS : s_vbeln FOR vbap-vbeln,
                 s_matnr FOR vbap-matnr.

TYPES : BEGIN OF ty_vbap,
          vbeln TYPE vbeln,
          posnr TYPE posnr,
          matnr TYPE matnr,
          netwr TYPE netwr,
        END OF ty_vbap.

DATA : it_vbap TYPE TABLE OF ty_vbap,
       wa_vbap TYPE ty_vbap.

DATA : new_po TYPE c.

SELECT vbeln posnr matnr netwr FROM vbap INTO TABLE it_vbap
  WHERE vbeln IN s_vbeln
  AND   matnr IN s_matnr.

SORT it_vbap BY vbeln.

LOOP AT it_vbap INTO wa_vbap.

  AT FIRST.
    WRITE :/ 'Order' COLOR 1, 12 'item' COLOR 2, 19 'Material' COLOR 2, 50 'Value' COLOR 3.
  ENDAT.

  AT NEW vbeln.
    new_po = 'X'.
  ENDAT.

  IF new_po = 'X'.
    WRITE :/ wa_vbap-vbeln, wa_vbap-posnr, wa_vbap-matnr, wa_vbap-netwr.
    new_po = ' '.
  Else.
    WRITE :/12 wa_vbap-posnr, wa_vbap-matnr, wa_vbap-netwr.
  ENDIF.


  AT END OF vbeln.
    SUM.
    WRITE :/39 wa_vbap-netwr COLOR 5.
  ENDAT.

ENDLOOP.

READ table

当你去读表,那你要把表读到哪里?
读到工作区里。
read table it_vbap into wa_vbap INDEX 5.
在这里插入图片描述

也就是说,read只能读一行
那么read其实有两种方式。在选择上,要么是选行数,要么给它个选项:
read table it_vbap into wa_vbap with key matnr = ‘M-01’.
key是列的意思。
在这里插入图片描述
但是read只能读一列,如果满足条件的不止一列呢?
那只有第一条满足条件的被读到。其他的就被ignore。
如果读到了,那就会有个值返回: sy-subrc = 0
除了以上写法,也可以写成:
read table it_vbap with key matnr = ‘M-01’ into wa_vbap.

APPEND

不得不说,这个的意思是附加。
也就是说本来人家都有了,你再加个。
那么一般是你有表的内容了,然后append一个wa_area的一行到表里面去。
在这里插入图片描述
在这里插入图片描述
append不仅仅是可以附加一行,也可以附加好几行。
也就是append lines of it_vbak1 to it_vbak.

对表进行join

要知道,并不是所有时候,表的join都是通过主键来进行的。
当我和别人join的不是主键,比如我要取得一个属性的文本,那我这个join的是我的一个属性值和别人的主键值。
这种就不会像主键那么快,因为他可能不唯一。

Join确实很好用。但是有些时候。我们要join的表很大,而且不是join它们的共同主键,那这时候,我join到三个表以上,就会相当影响性能了。
因为你得去遍历表啊,需要时间的。

比如说我需要的数据来自5个表。是的,干啥之前你得把需要的表理清关系。也就是你得知道你的表里有哪些数据,然后这些表的列都是啥意思,表列直接有啥包含关系。
而其中有两个表是有共同主键的。那这时候,我可以join这两个表。

一般就是select * * * * from table a as a inner join table b as b on a~A = b~A where * = parameter into table X.

而之前我们也看过了。
除了inner join之外,还可以用: for all entries in

for all entries in

也就是说这个也可以。
那怎么使用的呢?前面得有个主句表啊。就是说我前面已经把数据都拉进一个表了,然后后面还有一个表。
那么这个后面的表,得是个有值的表,啥意思呢?

就是要么你是从内表select几个字段已经到了你自定义的表。
要么你是已经join了的into的一个表。

然后我select *** from tableA into table it_tableA for all entries in tableB where it_tableA~a = tableB~A
这样我就把it_tableA里面的所有和B表的有相同键值的行给取到it_tableA里了。也就是做了个限制了。
但是这样免去了写很多的inner join。
而且也填充了我们需要的数据到这几个表中。当你必须要连接好多个表,而且这些表没有共同主键,那你就只能这么用。
用 for all entries in / move corresponding / read table / append /clear

TABLES:  vbak,  " Order Data
         tvakt, " Order Description text table
         tvzbt, " Payment terms text table
         vbkd,  " Order business data ( like payment terms , customer groups etc )
         t151t. " customer groups text table

*Join of VBAK and VBKD
TYPES : BEGIN OF ty_vbak_vbkd,
          vbeln TYPE vbak-vbeln,
          auart TYPE vbak-auart,
          erdat TYPE vbak-erdat,
          ernam TYPE vbak-ernam,
          kdgrp TYPE vbkd-kdgrp,
          zterm TYPE vbkd-zterm,
        END OF ty_vbak_vbkd,

* Order Type Description from table TVAKT
        BEGIN OF ty_tvakt,
          auart TYPE tvakt-auart,
          bezei TYPE tvakt-bezei,
        END OF ty_tvakt,

* Payment Terms
        BEGIN OF ty_tvzbt,
          zterm TYPE tvzbt-zterm,
          vtext TYPE tvzbt-vtext,
        END OF ty_tvzbt,

*Customer group texts from T151T
        BEGIN OF ty_t151t,
          kdgrp TYPE t151t-kdgrp,
          ktext TYPE t151t-ktext,
        END OF ty_t151t,

*Final structure to be written out on to the screen
        BEGIN OF ty_final,
          vbeln TYPE vbak-vbeln,
          auart TYPE vbak-auart,
          erdat TYPE vbak-erdat,
          ernam TYPE vbak-ernam,
          kdgrp TYPE vbkd-kdgrp,
          zterm TYPE vbkd-zterm,
          bezei TYPE tvakt-bezei,
          vtext TYPE tvzbt-vtext,
          ktext TYPE t151t-ktext,
        END OF ty_final.

*Internal tables
DATA :  it_vbak_vbkd TYPE TABLE OF ty_vbak_vbkd,
        it_tvakt     TYPE TABLE OF ty_tvakt,
        it_tvzbt     TYPE TABLE OF ty_tvzbt,
        it_t151t     TYPE TABLE OF ty_t151t,
        it_final     TYPE TABLE OF ty_final,


        wa_vbak_vbkd TYPE  ty_vbak_vbkd,
        wa_tvakt     TYPE  ty_tvakt,
        wa_tvzbt     TYPE  ty_tvzbt,
        wa_t151t     TYPE  ty_t151t,
        wa_final     TYPE  ty_final.


SELECT-OPTIONS :
  s_vbeln FOR vbak-vbeln,
  s_auart FOR vbak-auart,
  s_erdat FOR vbak-erdat,
  s_ernam FOR vbak-ernam,
  s_zterm FOR vbkd-zterm,
  s_kdgrp FOR vbkd-kdgrp.


START-OF-SELECTION.

  SELECT  vbak~vbeln
          vbak~auart
          vbak~erdat
          vbak~ernam
          vbkd~kdgrp
          vbkd~zterm
    FROM vbak AS vbak
    INNER JOIN vbkd AS vbkd
    ON vbak~vbeln = vbkd~vbeln
    INTO TABLE it_vbak_vbkd
    WHERE vbak~vbeln IN s_vbeln
    AND   vbak~auart IN s_auart
    AND   vbak~erdat IN s_erdat
    AND   vbak~ernam IN s_ernam
    AND   vbkd~posnr = '000000'
    AND   vbkd~zterm IN s_zterm
    AND   vbkd~kdgrp IN s_kdgrp.


  IF it_vbak_vbkd[] IS NOT INITIAL.

    SELECT auart bezei
      FROM tvakt
      INTO TABLE it_tvakt
      FOR ALL ENTRIES IN it_vbak_vbkd
      WHERE auart = it_vbak_vbkd-auart
      AND   spras = sy-langu.

    SELECT zterm vtext
        FROM tvzbt
        INTO TABLE it_tvzbt
        FOR ALL ENTRIES IN it_vbak_vbkd
        WHERE zterm = it_vbak_vbkd-zterm
        AND   spras = sy-langu.

    SELECT kdgrp ktext
        FROM t151t
        INTO TABLE it_t151t
        FOR ALL ENTRIES IN it_vbak_vbkd
        WHERE kdgrp = it_vbak_vbkd-kdgrp
        AND spras = sy-langu.

  ENDIF.

  LOOP AT it_vbak_vbkd INTO wa_vbak_vbkd.
    MOVE-CORRESPONDING wa_vbak_vbkd TO wa_final. *此处是一行一行的,把第一个工作区间一行的列转移到目标工作区间的一行的其中相对应的列。然后其余的在这行上面的列,在下面的表上面读取。

    READ TABLE it_tvakt INTO wa_tvakt WITH KEY auart = wa_vbak_vbkd-auart. *注意这个语法,read table  into with key/ loop at into where  那么with的这个key值,是相对于已经存在于上面的工作区的,也就是我们第一个loop的工作区。因为那是第一行。
    IF sy-subrc = 0.
      MOVE wa_tvakt-bezei TO wa_final-bezei.*如果有值了,再把这个值放到目标工作区。在loop里面的read,也是一行一行的读。所以说不能在loop里面再套一个loop了,那是双重循环了。
    ENDIF.

    READ TABLE it_tvzbt INTO wa_tvzbt WITH KEY zterm = wa_vbak_vbkd-zterm.
    IF sy-subrc = 0.
      MOVE wa_tvzbt-vtext TO wa_final-vtext.
    ENDIF.

    READ TABLE it_t151t INTO wa_t151t WITH KEY kdgrp = wa_vbak_vbkd-kdgrp.
    IF sy-subrc = 0.
      MOVE wa_t151t-ktext TO wa_final-ktext.
    ENDIF.



    APPEND wa_final TO it_final.* 最后把值append进table
    CLEAR wa_final.
  ENDLOOP.

  BREAK-POINT.

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaomici

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值