SAP常見查詢組合


做SAP開發的,SELECT是必不可少的。新語法出了不少'新鮮'的語法,用法也是五花八門。

新語法有新語法的好處,老語法有老語法的優勢。

新語法里把很多的邏輯處理,分組,排重,內表處理全都放到一些關鍵字來處理。看起來是簡化了代碼,方便開發處理數據,但是缺少了必要的數據處理的思維邏輯,讓人變得傻了。

SAP作為企業ERP中最大的BOSS,一直以來都不是以美觀和高科技贏得口碑。作為一個使用者來說,ERP最理想的樣子就是穩定,快捷,准確等。

在我看來,ERP是千萬量級,億級,十億級,百億級的數據處理,效率最高的才是最好的。

 

下面開始說說一些常見的SQL樣例:

1,單獨的select

一些簡單的select是最基礎的了。

SELECT result 
       FROM source 
       [[FOR ALL ENTRIES IN itab] WHERE sql_cond] 
       [GROUP BY group] [HAVING group_cond] 
       [ORDER BY sort_key] 
       INTO|APPENDING target 
       [additions]. 
  ... 
[ENDSELECT]. 

這是SAP的F1說明,emmm...首先這個select endselect不建議使用了。select table的時候就對應好into table。select...endselect是單條處理,多次IO交互。

SAP給的建議是少次數的數據庫IO處理,短時間的數據庫IO。

[GROUP BY group] [HAVING group_cond] 這個稍微常用點,在分組或者取聚集數據的時候可以加。
比如:查詢MSEG中各移動類型的數量,加個Group by就可以直接取。例子如下(因為不是ECC系統,所以借其他表演示):
  SELECTA~PROCESS_TYPE
         A~STAT_USER
         sum( ZAF_PRICE ) as ZAF_PRICE
    INTO CORRESPONDING FIELDS OF TABLE GT_ORDER
    FROM ZHSB_ORDER_INDEX AS A
    INNER JOIN CRMD_ORDERADM_H AS B
    ON A~GUID = B~GUID
    WHERE (GT_WHERE)
    AND A~SALES_ORG IN S_ORG
    AND A~PROCESS_TYPE = P_TYPE
    AND B~CHANGED_AT BETWEEN GV_FROM AND GV_TO
    GROUP BY a~PROCESS_TYPE a~STAT_USER.

這里就可以直接查詢某些條件組合下的合計值。

2.關聯查詢:

常用INNER JOIN,LEFT OUT JOIN 等。

SELECT - JOIN 
Syntax 
... [(] {data_source [AS tabalias]}|join 
          {[INNER] JOIN}|{LEFT|RIGHT [OUTER] JOIN} 
             {data_source [AS tabalias]}|join ON join_cond [)] ...  . 
Addition: 
... ON join_cond 
Effect 
Joins the columns of two or more database tables in a results set in a join expression. A join expression links a left side to a right side, using either [INNER] JOIN or LEFT|RIGHT [OUTER] JOIN. A join expression can be an inner join (INNER) or an outer join (LEFT OUTER) or RIGHT OUTER) join. Every join expression must contain a join condition join_cond after ON (see below). The following applies to entries specified on the left side and on the right side: 

LEFT和RIGHT是以誰為主的差別。上面的例子中已經有了INNER JOIN,下面再添加個文本的LEFT JOIN如下:

  SELECT A~PROCESS_TYPE
         A~STAT_USER
         C~P_DESCRIPTION
         sum( ZAF_PRICE ) as ZAF_PRICE
    INTO CORRESPONDING FIELDS OF TABLE GT_ORDER
    FROM ZHSB_ORDER_INDEX AS A
    INNER JOIN CRMD_ORDERADM_H AS B
    ON A~GUID = B~GUID
    LEFT JOIN CRMC_PROC_TYPE_T AS C
    ON A~PROCESS_TYPE = C~PROCESS_TYPE
    WHERE (GT_WHERE)
    AND A~SALES_ORG IN S_ORG
    AND A~PROCESS_TYPE = P_TYPE
    AND B~CHANGED_AT BETWEEN GV_FROM AND GV_TO
    GROUP BY a~PROCESS_TYPE a~STAT_USER C~P_DESCRIPTION.

注意*:LEFT JOIN里的字段不可以當作查詢條件。(上面的WHERE CLUSE里不能有 C~字段)。

 

管理查詢中還有個是

FOR ALL ENTRIES IN

很多人都不喜歡這個,覺得這個效率低,還沒有INNER JOIN省事。^_^看怎么用吧,不要一竿子打死一船人。

SAP給的解釋自己看F1,這里就不多說了,我說個用這個提效的例子:還是上面的LEFT JOIN。

SAP的JOIN是表之間的關聯,當主表的數據量達到一定數量級,不管JOIN的是不是文本表,都會加重負擔,比如說上面的SLECT中是先GROUP再取C表的描述還是先JOIN再取描述,然后一起GROUP呢?。

這時候怎么取文本表效率高,速度快呢?因為上面的SELECT已經有GROUP了,查出的結果內表數量可想而知很少很少。

注*:這里以及下面說的文本表不是具體指文本表,而是代指關聯輔表。

這時候用FOR ALL ENTRIES IN來查文本表數據,然后循環loop處理,效率就上來了。

    SELECT * INTO CORRESPONDING FIELDS OF TABLE gt_order
      FROM CRMC_PROC_TYPE_T
      FOR ALL ENTRIES IN gt_order
      WHERE PROCESS_TYPE = gt_order-PROCESS_TYPE.

在主表后面再加個文本表,用用FOR ALL ENTRIES IN也就順理成章了。

注意*:如果文本表本身數據量並不多,那么甚至還可以省略這個FOE ALL ENTRIES IN,直接取個全表也是可以的,這時候效率幾乎相當的。

 

3.層級查詢:

在一些復雜條件的查詢中,很難去處理到底怎么查詢才是最優的。下面列幾個表,順便說明其中的關系:

BUT000:BP主表

BUT020:BP地址關系主表

ADRC:地址主表

ADR2:電話主表

ADR3:FAX

ADR6:郵箱

(注*這幾個表,關系相對明確,很多時候比這更麻煩)

 

如果這時候要按電話號碼來查找BP,那么能想到的就是從ADR2->BUT020->BUT000

如果這時候是按BP來查,那么就是BUT000->BUT020->ADR2,ADRC...

如果按郵箱,郵編又是另外的情況了。

那么這時候怎么查詢呢?一個select肯定不能完全解決問題的,不僅效率不能讓人滿意,結果也不一樣就是想要的。

這時候分層級查詢就很好的處理這種情況了。

設定LEVEL1,2,3等等。

REPORT zlytest112.

TABLES:but000,but020,adrc,adr2,adr3,adr6.

DATA:lv_level TYPE c.

SELECTION-SCREEN:BEGIN OF BLOCK blk01 WITH FRAME TITLE text-001.
SELECT-OPTIONS:
s_part FOR but000-partner,
s_name FOR but000-name1_text,
s_grop FOR but000-group,
s_rego FOR adrc-region,
s_tel  FOR adr2-tel_number,
s_fax  FOR adr3-fax_number,
s_emil FOR adr6-smtp_addr.
SELECTION-SCREEN END OF BLOCK blk01.


START-OF-SELECTION.
  "設置分級條件
  IF s_tel IS NOT INITIAL OR s_fax IS NOT INITIAL OR s_emil.
    lv_level  = '3'.
  ENDIF.

  IF s_part IS NOT INITIAL OR s_name IS NOT INITIAL OR s_grop IS NOT INITIAL.
    lv_level  = '1'.
  ENDIF.

  IF s_rego IS NOT INITIAL.
    lv_level  = '2'.
  ENDIF.
  

  CASE lv_level.
    WHEN '1'.
      PERFORM SEL_BUT000.
      PERFORM FOA_ADRC.
      PERFORM FOA_ADR2.
      PERFORM FOA_ADR3.
      PERFORM FOA_ADR6.
    WHEN '2'.
      PERFORM SEL_ADRC.
      PERFORM FOR_BUT000.
      PERFORM FOA_ADR2.
      PERFORM FOA_ADR3.
      PERFORM FOA_ADR6.
    WHEN '3'.
      PERFORM SEL_ADRX.
      PERFORM FOR_BUT000.
      PERFORM FOA_ADRX.
      PERFORM FOA_ADRX.
      PERFORM FOA_ADRX.
    WHEN OTHERS.
  ENDCASE.
  
  

具體的FORM里的代碼就省了。這里是強關聯關系,所以可以用一個SELECT就能替換調,但是效率就差了千萬倍了。如果是弱關聯,那么就不是一個SELECT能解決的事了。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM