(2) 确定了表连接的次序后,应考虑将查询条件尽量限制在靠前的表里。比如选择屏幕上有个物料号的查询条件,而我们知道订单VBAP和交货单LIPS均有物料号,那就应该视情况而定,如果表连接中VBAP更早出现,那么WHERE子句中就使用vbap~matnr IN s_matnr,反之就是lips~matnr IN s_matnr。
还有一种有效的办法是,通过TVKO查询到当期公司代码所对应的全部销售组织,从而组建一个RANGE出来,再根据此RANGE查询LIKP。当然要注意RANGE的行项目有上限的,在ECC6中大概2万行将导致ABAP DUMP。
提示:DATA r_vkorg TYPE RANGE OF likp-vkorg.
SIGN = ‘I’, OPTION = ‘EQ’, LOW = ‘XXXX’ 即可往r_vkorg中放入多个单值。
3, For All Entries与Select Single的比较
就个人而言,笔者不是很喜欢For All Entries语句,因为它的缺点多于优点。很多人都会说,为什么呀,For All Entries不是比Select Single快么?事实到底怎样呢,让我们做个比较。
假设我们有个内表代表销售订单的行项目,该内表有10万行。此时我们要根据LIPS的VGBEL和VGPOS,查询这些订单行项目对应的交货单行项目。
如果用SELECT SINGLE的话写法很简单:
LOOP AT it_vbap INTO wa_vbap.
SELECT SINGLE vbeln posnr
FROM lips INTO (wa_vbap-vbeln_vl, wa_vbap-posnr_vl)
WHERE vgbel = wa_vbap-vbeln AND
vgpos = wa_vbap-posnr AND
vgtyp = ‘C’.
MODIFY it_vbap FROM wa_vbap.
ENDLOOP.
如果用For All Entries则写法分2步:
SELECT vbeln posnr
FROM lips INTO TABLE it_lips
For All Entries IN it_vbap
WHERE vgbel = it_vbap-vbeln AND
vgpos = it_vbap-posnr AND
vgtyp = ‘C’. “此交货单是根据订单创建的
LOOP AT it_vbap INTO wa_vbap.
READ TABLE it_lips INTO wa_lips WITH KEY vgbel = wa_vbap-vbeln
vgpos = wa_vbap-vgpos.
IF sy-subrc = 0.
wa_vbap-vbeln_vl = wa_lips-vbeln.
wa_vbap-posnr_vl = wa_lips-posnr.
MODIFY it_vbap FROM wa_vbap.
ENDIF.
ENDLOOP.
对于SELECT SINGLE而言,由于LIPS有个VGB的SAP自带索引,每次查询都挺快,即便循环10万次,速度虽然快不了但也没什么大的危害。
对于For All Entries的第一步,的确比SELECT SINGLE快些,本来10万次的SELECT SINGLE,变成了1万次的查询(如果BASIS设置了参数为10),每次查询10个订单行项目。但是第二步就很慢了, 暂估it_lips为8万行,则对于it_vbap的10万个行项目,有8万个行项目执行READ TABLE语句平均需要4万次才能搜索到it_lips的目标行,另有2万个行项目将读遍it_lips然后才发现没有对应的目标行。所以我们一共需要搜索48亿次,太慢了!
在此针对For All Entries的使用提出几点意见:
(1)如果是根据某数据量大的内表用For All Entries读取数据量小的配置表,比如TVAK/T006等,那不如把For All Entries直接去掉,把表里的几十条数据全部取出。
(2)使用For All Entries时,SELECT语句后面的字段必须包含所查表关键字段。比如上面的vbeln/posnr就是lips的关键字段。如果不含关键字段,比如SELECT lfimg FROM lips For All Entries ***,那么当LIPS中两个条目关键字段不同而lfimg相同时,会被SAP自动过滤掉一条。
(3)上面关于性能问题,应该利用BINARY SEARCH、SORTED TABLE或者HASHED TABLE来解决。详见下面第四节。