ABAP BINARY SEARCH--二分法



二分法檢索(binary search)又稱折半檢索,其基本思想是設字典中的元素從小到大有序地存放在數組(array)中:  

 首先將給定值key與字典中間位置上元素的關鍵碼(key)比較,如果相等,則檢索成功;    

  否則,

若key小,則在字典前半部分中繼續進行二分法檢索;           

若key大,則在字典後半部分中繼續進行二分法檢索。    

 這樣,經過一次比較就縮小一半的檢索區間,如此進行下去,直到檢索成功或檢索失敗。   

 二分法檢索是一種效率較高的檢索方法,要求字典在順序表中按關鍵碼排序

對於二分查找,表必須根據特殊的搜索關鍵字來升序排列,否則這個搜索不會找到正確的行。

例子:

CLEARlv_gl_s,lv_gl_h.
      READ TABLE it_gl_result INTO lv_gl_s   WITH KEY  racct <fs_gl>-racct drcrk 'S' BINARY SEARCH.
      READ TABLE it_gl_result INTO lv_gl_h WITH KEY  racct <fs_gl>-racct drcrk 'H' BINARY SEARCH.
      lv_gl_data-ba_amount lv_gl_s-hslvt ABSlv_gl_h-hslvt ).


__________________________________________________________________________________________________________________________________________

在維護公司SAP的過程中,遇到一個問題,困擾了很久!

簡單描述一下問題:(爲了不牽扯公司業務,這是抽取問題)將主要的三個字段

存在一個內表TAB2,如圖所示:

需要強調一下,真是的內表比TAB2要多很多字段,(這是重點

 

首先對系統中真實的內表進行了排序,其中主要的三個字段的排序如TAB2所示,

(如果是內表TAB2,對COLUMN1排序的話,默認的COLUMN3也會自動安裝升序排列):

SORT  TAB2  BY COLUMN1 .

得到下圖:

 

使用二分查找:

READ TABLE TAB2 WITH KEY COLUMN1 = '0800113864' COLUMN2 = '2012' COLUMN3 = '3018054318' BINARY SEARCH.

返回 SY-SUBRC = 8.

即查詢沒有相關數據!

 

這就是問題的情況所在!!

 

我發現問題的過程可以理解爲如下步驟:

1. 首先定位到5條記錄的中間那條記錄,即第3條記錄,然後對比COLUMN3。

2. 第3條記錄的COLUMN3數據如果不等於 '3018054318' ,則從第3條至第5條記錄的中間那條記錄,即第4條記錄,然後對比COLUMN3。

3. 第4條記錄的COLUMN3數據如果不等於 '3018054318' ,則比較第5條記錄然後對比COLUMN3。

4. 由於都沒有等於 '3018054318' 的記錄,則返回SY-SUBRC = 8。

 

解決此問題的關鍵:

在於對內表的排序,如果在

READ TABLE TAB2 WITH KEY COLUMN1 = '0800113864' COLUMN2 = '2012' COLUMN3 = '3018054318' BINARY SEARCH.

時候,使用到COLUMN1 = '0800113864' COLUMN2 = '2012' COLUMN3 = '3018054318' ,則對此係統中內表排序的時候需要依照此三個字段進行排序。

______________________________________________________________________________________________________________________________

1、使用where語句
不推薦
Select * from zflight.
Check : zflight-airln = ‘LF’ and zflight-fligh = ‘BW222’.
Endselect.
推薦
Select * from zflight where airln = ‘LF’ and fligh = ‘BW222’.
Endselect.

2、使用聚合函數
不推薦
Maxnu = 0.
Select * from zflight where airln = ‘LF’ and cntry = ‘IN’.
Check zflight-fligh > maxnu.
Maxnu = zflight-fligh.
Endselect.
推薦
Select max( fligh ) from zflight into maxnu where airln = ‘LF’ and cntry = ‘IN’.


3、使用視圖代替基本表查詢
不推薦
Select * from zcntry where cntry like ‘IN%’.
Select single * from zflight where cntry = zcntry-cntry and airln = ‘LF’.
Endselect.
推薦
Select * from zcnfl where cntry like ‘IN%’ and airln = ‘LF’.
Endselect.

4、使用INTO table 代替select endselect
不推薦
Refresh: int_fligh.
Select * from zflight into int_fligh.
Append int_fligh. Clear int_fligh.
Endselect.
推薦
Refresh: int_fligh.
Select * from zflight into table int_fligh.

5、使用批量修改內表代替逐行修改
不推薦
Loop at int_fligh.
If int_fligh-flag is initial.
Int_fligh-flag = ‘X’.
Endif.
Modify int_fligh.
Endloop.
推薦
Int_fligh-flag = ‘X’.
Modify int_fligh transporting flag where flag is initial.

6、使用二分法查詢,提高查詢內表數據速度
不推薦
Read table int_fligh with key airln = ‘LF’.
推薦
Read table int_fligh with key airln = ‘LF’ binary search.


SAP ABAP 性能優化技巧 — 使用二分查找(Binary Search)選項

READ命令使用順序查找數據表,這會降低處理速度。取而代之,使用binary search的附加命令,可以使用二分查找算法,可以幫助加快內表查找速度。 在使用binary search之前必須首先將內表排序,否則有可能找不到記錄,因爲二分查找反覆將查找區間對半劃分,如果要查找的值小於查找區間的中間位置的數據項值,則查找區間將縮小到前半個區間,否則查找將侷限於後半區間.

 

不推薦使用:

 

Read table int_fligh with key airln = ‘LF’.

 

 

推薦使用:

SORT int_fligh by airln.
Read table int_fligh with key airln = ‘LF’ binary search.

 

應用:

with key 後面不能使用比較符 < >.  

read table itab with key   matnr = lt_mseg_n-matnr

                            pvprs > 0 .   這種寫法不對。

 

可以變通的寫這條語句。

  LOOP at lt_ckmlcr WHERE  matnr = lt_mseg_n-matnr AND pvprs > 0.

.........

  exit.

endloop.

7、兩個內表添加使用批量增加代替逐行
不推薦
Loop at int_fligh1.
Append int_fligh1 to int_fligh2.
Endloop.
推薦
Append lines of int_fligh1 to int_fligh2.

8、 使用FOR ALL Entries
不推薦
Loop at int_cntry.
Select single * from zfligh into int_fligh where cntry = int_cntry-cntry.
Append int_fligh.
Endloop.
推薦
Select * from zfligh appending table int_fligh
For all entries in int_cntry
Where cntry = int_cntry-cntry.

9、使用sort by 代替order by

10、避免使用SELECT DISTINCT語句
使用的 ABAP SORT + DELETE ADJACENT DUPLICATES 代替.


11、兩個實例

DATA: BEGIN OF it_mara OCCURS 0,
matnr LIKE mara-matnr,
maktx LIKE makt-maktx,
END OF it_mara.
第一種寫法:
Select matnr
INTO it_mara
FROM mara.
APPEND it_mara.
ENDSelect.
第二種寫法(high performace):
Select matnr
INTO TABLE it_mara
FROM mara.
==========================================
DATA: BEGIN OF it_mara OCCURS 0,
matnr LIKE mara-matnr,
maktx LIKE makt-maktx,
END OF it_mara.
DATA: BEGIN OF it_makt OCCURS 0,
matnr LIKE mara-matnr,
maktx LIKE makt-maktx,
END OF it_makt.
第一種寫法:
LOOP AT it_mara.
Select SINGLE maktx
INTO it_mara-maktx
FROM makt
Where matnr = it_mara-matnr AND
spras = sy-langu.
MODIFY it_mara TRANSPORTING maktx.
ENDLOOP.
第二種寫法(high performace)
Select matnr maktx
INTO TABLE it_makt
FROM makt
FOR ALL ENTRIES IN it_mara
Where matnr = it_mara-matnr and
spras = sy-langu.
=========================================

1 數據——>工作區,工作區——>內表,
2 數據——>內表
很明顯少了一個過程 效率自然高了 如果數據量越大,效果是可想而知的


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章