카테고리 없음

[ABAP] Internal Table Deep Dive

TheSapper 2026. 4. 4. 22:00
반응형

ABAP Internal Table 종류 및 Key 활용 노하우

1. Inter table의 3가지 종류

" -------------------------------------------------------
" 1. STANDARD TABLE - 기본형
" -------------------------------------------------------
DATA lt_standard TYPE STANDARD TABLE OF mara
  WITH NON-UNIQUE KEY matnr.   " 중복 허용

" 특징: 순차 접근, INDEX 사용 가능
" 용도: 순서가 중요한 데이터, 대량 APPEND

" -------------------------------------------------------
" 2. SORTED TABLE - 정렬형
" -------------------------------------------------------
DATA lt_sorted TYPE SORTED TABLE OF mara
  WITH UNIQUE KEY matnr.       " 중복 불가 (UNIQUE)
" 또는
DATA lt_sorted2 TYPE SORTED TABLE OF mara
  WITH NON-UNIQUE KEY matnr mtart.  " 중복 허용

" 특징: 항상 정렬 유지, Binary Search 자동 적용
" 용도: READ/LOOP WHERE 성능이 중요한 경우

" -------------------------------------------------------
" 3. HASHED TABLE - 해시형
" -------------------------------------------------------
DATA lt_hashed TYPE HASHED TABLE OF mara
  WITH UNIQUE KEY matnr.       " 반드시 UNIQUE만 가능

" 특징: Hash 알고리즘으로 O(1) 접근
" 용도: 대용량 단건 READ (마스터 데이터 캐싱)

2. 성능 비교

구분 STANDARD SORTED HASHED
APPEND ✅ 빠름 ⚠️ 정렬유지 비용 ❌ 느림
READ (KEY) ❌ 순차O(n) ✅ BinaryO(log n) ✅✅ HashO(1)
READ (INDEX) ✅ 가능 ✅ 가능 ❌ 불가
LOOP WHERE ⚠️ 전체탐색 ✅ 부분탐색 ⚠️ 전체탐색
중복 허용 선택
메모리 보통 보통 많음

3. KEY 선언 노하우

Key Characteristics by Table Category
  • Standard Tables: Use only non-unique primary keys. If you do not specify a key type, ABAP implicitly assigns WITH NON-UNIQUE DEFAULT KEY.
  • Sorted Tables: Can use either UNIQUE or NON-UNIQUE keys. When using a non-unique key, the table remains sorted by that key, but duplicate entries are permitted.
  • Hashed Tables: Cannot use non-unique keys; they require a UNIQUE primary key to function.
  • Secondary Keys: You can define up to 15 secondary keys for an internal table. These can be defined as NON-UNIQUE SORTED KEY to facilitate alternative sorted access paths while allowing duplicates
Behavior with Duplicate Entries
  • Search Results: When using a READ TABLE statement with a non-unique key, the system returns the first record it finds that matches the criteria.
  • Insertion Order: For sorted tables with non-unique keys, duplicate lines are typically inserted before any existing identical entries to maintain a specific internal order.
  • Performance: Searching a Standard table with a non-unique key involves a linear search (unless sorted and searched with BINARY SEARCH), whereas a Sorted table uses a binary search automatically.
Key Composition
The fields included in a default key vary based on the row type:
  • Structured Row Type: The key consists of all character-like and byte-like components (e.g., C, N, D, T, STRING, XSTRING).
    • Numeric types (like I, P, F) and internal tables are excluded.
    • Substructures are resolved into their elementary components for key formation.
  • Elementary Row Type: The key is the entire row.
  • Table-like Row Type: If the row type itself is another internal table, the default key is empty

3-1. UNIQUE vs NON-UNIQUE KEY

" UNIQUE: 중복 INSERT 시 런타임 에러 → 데이터 정합성 보장
DATA lt_unique TYPE HASHED TABLE OF /scwm/aqua
  WITH UNIQUE KEY lgnum lgpla matnr charg.

" NON-UNIQUE: 중복 허용 → SORTED에서만 사용 가능
DATA lt_non_unique TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY lgnum matnr.

" ⚠️ HASHED는 반드시 UNIQUE KEY만 가능

3-2. Secondary Key (보조 키) 활용

" Primary Key + Secondary Key 동시 선언
DATA lt_multi_key TYPE STANDARD TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY primary_key        " Primary: 기본
    COMPONENTS lgnum lgpla matnr
  WITH NON-UNIQUE SORTED KEY key_by_hu   " Secondary: HU 기준
    COMPONENTS huident
  WITH NON-UNIQUE SORTED KEY key_by_cat  " Secondary: CAT 기준
    COMPONENTS cat matnr.

" Secondary Key로 READ
READ TABLE lt_multi_key
  WITH TABLE KEY key_by_hu               " 보조키 지정
  COMPONENTS huident = 'HU0001234'
  INTO DATA(ls_result).

" Secondary Key로 LOOP
LOOP AT lt_multi_key INTO DATA(ls)
  USING KEY key_by_cat                   " 보조키로 정렬된 순서로 루프
  WHERE cat = 'F'.
ENDLOOP.

 

3-3. EMPTY KEY (키 없음)

" 키 비교 없이 순수 목록으로만 쓸 때
DATA lt_log TYPE STANDARD TABLE OF string
  WITH EMPTY KEY.

APPEND '처리 시작' TO lt_log.
APPEND '처리 완료' TO lt_log.​

4. 실무 노하우 - 상황별 패턴

패턴 1: 대용량 마스터 데이터 캐싱

" ✅ HASHED TABLE로 자재 마스터 캐싱
DATA lt_mara TYPE HASHED TABLE OF mara
  WITH UNIQUE KEY matnr.

" DB에서 한번만 조회
SELECT * FROM mara INTO TABLE @lt_mara
  WHERE mtart = 'FERT'.

" 이후 O(1) 접근
READ TABLE lt_mara
  WITH TABLE KEY matnr = lv_matnr
  INTO DATA(ls_mara).

" ❌ 잘못된 방식 - STANDARD TABLE에 BINARY SEARCH
READ TABLE lt_standard
  WITH KEY matnr = lv_matnr   " O(n) 순차탐색 발생!
  INTO DATA(ls).
 

패턴 2: SORTED TABLE로 LOOP 최적화

" ✅ SORTED TABLE - LOOP WHERE가 부분탐색으로 최적화
DATA lt_stock TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY lgnum lgpla matnr.

SELECT * FROM /scwm/aqua
  INTO TABLE @lt_stock
  WHERE lgnum = '1710'.

" SORTED KEY 앞부분 조건 → Binary Search 자동 적용
LOOP AT lt_stock INTO DATA(ls_stock)
  WHERE lgnum = '1710'
    AND lgpla = 'BIN-A-001'.   " ✅ 빠른 부분탐색
ENDLOOP.

" ❌ KEY 앞부분 조건 없으면 효과 없음
LOOP AT lt_stock INTO DATA(ls_stock)
  WHERE matnr = '000000001234'. " ❌ lgnum/lgpla 없어서 전체탐색
ENDLOOP.
 

패턴 3: GROUP BY 집계 대체

" SORTED TABLE + LOOP AT GROUP 으로 집계
DATA lt_ord TYPE SORTED TABLE OF /scwm/ordim_o
  WITH NON-UNIQUE KEY matnr charg.

SELECT * FROM /scwm/ordim_o
  INTO TABLE @lt_ord
  WHERE lgnum = '1710'.

" 자재별 그룹 집계
LOOP AT lt_ord INTO DATA(ls_ord)
  GROUP BY ( matnr = ls_ord-matnr
             charg = ls_ord-charg )
  ASSIGNING FIELD-SYMBOL(<grp>).

  DATA(lv_total) = CONV /scwm/de_menge_puom( 0 ).

  LOOP AT GROUP <grp> INTO DATA(ls_item).
    lv_total += ls_item-anfme.
  ENDLOOP.

  WRITE: / <grp>-matnr, <grp>-charg, lv_total.
ENDLOOP.

패턴 4: Secondary Key로 다중 조건 최적화

" EWM 재고 + WT 통합 조회 최적화 예시
DATA lt_aqua TYPE STANDARD TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY primary_key
    COMPONENTS lgnum lgpla matnr charg        " Bin 기준 조회용
  WITH NON-UNIQUE SORTED KEY sk_hu
    COMPONENTS huident                         " HU 기준 조회용
  WITH NON-UNIQUE SORTED KEY sk_matnr
    COMPONENTS matnr cat.                      " 자재+카테고리 조회용

" Bin 기준 조회
READ TABLE lt_aqua
  WITH TABLE KEY primary_key
  COMPONENTS lgnum = '1710'
             lgpla = 'BIN-A-001'
             matnr = p_matnr
             charg = p_charg
  INTO DATA(ls_bin).

" HU 기준 조회 (Secondary Key)
READ TABLE lt_aqua
  WITH TABLE KEY sk_hu
  COMPONENTS huident = 'HU0001234'
  INTO DATA(ls_hu).

" 자재+카테고리 LOOP (Secondary Key)
LOOP AT lt_aqua INTO DATA(ls)
  USING KEY sk_matnr
  WHERE matnr = p_matnr
    AND cat   = 'F'.
ENDLOOP.
 

5. 자주 하는 실수 & 해결

" ❌ 실수 1: STANDARD TABLE에 READ WITH KEY → 느림
READ TABLE lt_standard WITH KEY matnr = lv_matnr
  INTO DATA(ls).  " O(n) 발생

" ✅ 해결: BINARY SEARCH 추가 (단, 정렬 선행 필요)
SORT lt_standard BY matnr.
READ TABLE lt_standard WITH KEY matnr = lv_matnr
  BINARY SEARCH INTO DATA(ls).  " O(log n)

" -------------------------------------------------------
" ❌ 실수 2: LOOP 안에서 READ → N*N 성능 최악
LOOP AT lt_ordim INTO DATA(ls_ordim).
  READ TABLE lt_aqua            " ← LOOP 안 READ = N² !
    WITH KEY lgpla = ls_ordim-vlpla
    INTO DATA(ls_aqua).
ENDLOOP.

" ✅ 해결: lt_aqua를 HASHED/SORTED로 선언
DATA lt_aqua_h TYPE HASHED TABLE OF /scwm/aqua
  WITH UNIQUE KEY lgpla matnr charg.

LOOP AT lt_ordim INTO DATA(ls_ordim).
  READ TABLE lt_aqua_h          " O(1) 접근
    WITH TABLE KEY
      lgpla = ls_ordim-vlpla
      matnr = ls_ordim-matnr
      charg = ls_ordim-charg
    INTO DATA(ls_aqua).
ENDLOOP.

" -------------------------------------------------------
" ❌ 실수 3: SORTED TABLE KEY 순서 무시
DATA lt_sorted TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY lgnum lgpla matnr.

" KEY = lgnum + lgpla + matnr 순서인데
LOOP AT lt_sorted INTO DATA(ls)
  WHERE matnr = p_matnr.  " ❌ 첫번째 KEY(lgnum) 빠져서 전체탐색
ENDLOOP.

" ✅ KEY 앞 컴포넌트부터 조건 지정
LOOP AT lt_sorted INTO DATA(ls)
  WHERE lgnum = p_lgnum   " ✅ 첫번째
    AND lgpla = p_lgpla   " ✅ 두번째
    AND matnr = p_matnr.  " ✅ 세번째
ENDLOOP.

6. 선택 기준 요약 플로우

Internal Table 선택
        │
        ├─ 단건 READ가 주목적?
        │       ├─ 키 중복 없음  → HASHED TABLE  ✅ O(1)
        │       └─ 키 중복 있음  → SORTED TABLE  ✅ O(log n)
        │
        ├─ LOOP + 범위 조건이 주목적?
        │       └─ SORTED TABLE (KEY 앞부분 조건 필수)
        │
        ├─ 순서/INDEX가 중요?
        │       └─ STANDARD TABLE + BINARY SEARCH
        │
        └─ 단순 목록 누적 (APPEND만)?
                └─ STANDARD TABLE WITH EMPTY KEY
 
Secondary Key는 하나의 테이블을 여러 기준으로 조회해야 할 때
테이블을 중복 선언하지 않아도 되므로 메모리와 성능 모두 잡을 수 있는 핵심 노하우입니다!

SORTED TABLE Key 자동 정렬 동작 방식

" SORTED TABLE → INSERT/APPEND 시 자동 정렬 ✅
" Secondary SORTED KEY → 정렬 안됨! 조회 최적화만 ✅
 

1. SORTED TABLE (Primary Key) - 자동 정렬 O

DATA lt_sorted TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY matnr lgpla.

" 순서 상관없이 INSERT해도 항상 matnr+lgpla 기준 정렬 유지
INSERT VALUE #( matnr = 'C' lgpla = 'BIN-3' quan = 10 ) INTO TABLE lt_sorted.
INSERT VALUE #( matnr = 'A' lgpla = 'BIN-1' quan = 30 ) INTO TABLE lt_sorted.
INSERT VALUE #( matnr = 'B' lgpla = 'BIN-2' quan = 20 ) INTO TABLE lt_sorted.

" 결과: A-BIN1 / B-BIN2 / C-BIN3  ← 자동 정렬됨
LOOP AT lt_sorted INTO DATA(ls).
  WRITE: / ls-matnr, ls-lgpla.  " A, B, C 순으로 출력
ENDLOOP.

" ⚠️ 단, APPEND는 사용 불가 (정렬 순서 보장 불가하므로 에러)
APPEND VALUE #( ... ) TO lt_sorted.  " ❌ 런타임 에러!
" 반드시 INSERT INTO TABLE 사용
INSERT VALUE #( ... ) INTO TABLE lt_sorted.  " ✅

2. Secondary SORTED KEY - 자동 정렬 X, 탐색 최적화만 O

DATA lt_standard TYPE STANDARD TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY primary_key
    COMPONENTS lgpla matnr
  WITH NON-UNIQUE SORTED KEY sk_matnr   " ← 이름만 SORTED
    COMPONENTS matnr cat.

APPEND VALUE #( matnr = 'C' lgpla = 'BIN-3' ) TO lt_standard.
APPEND VALUE #( matnr = 'A' lgpla = 'BIN-1' ) TO lt_standard.
APPEND VALUE #( matnr = 'B' lgpla = 'BIN-2' ) TO lt_standard.

" 일반 LOOP → 입력 순서 그대로 C, A, B 출력
LOOP AT lt_standard INTO DATA(ls).
  WRITE: / ls-matnr.   " C → A → B (정렬 안됨!)
ENDLOOP.

" USING KEY 지정 LOOP → A, B, C 순으로 출력 ✅
LOOP AT lt_standard INTO DATA(ls)
  USING KEY sk_matnr.  " ← 이때만 정렬된 순서로 접근
  WRITE: / ls-matnr.   " A → B → C
ENDLOOP.

3. Secondary SORTED KEY 내부 동작 원리

STANDARD TABLE 실제 메모리
┌─────────────────────────┐
│ [1] matnr=C, lgpla=BIN3 │  ← 입력 순서 그대로
│ [2] matnr=A, lgpla=BIN1 │
│ [3] matnr=B, lgpla=BIN2 │
└─────────────────────────┘

Secondary SORTED KEY (sk_matnr) 내부 인덱스
┌──────────────────────────┐
│ matnr=A → 행 [2] 포인터  │  ← 별도 정렬 인덱스 유지
│ matnr=B → 행 [3] 포인터  │
│ matnr=C → 행 [1] 포인터  │
└──────────────────────────┘

→ 데이터 자체는 안 움직임
→ 인덱스만 정렬되어 있어서 READ/LOOP가 빠른 것

 

4. 둘의 차이 완전 정리

구분 SORTED TABLE Secondary SORTED KEY
데이터 자동 정렬 ✅ 항상 정렬 유지 ❌ 데이터 순서 불변
APPEND 사용 ❌ 불가 (에러) ✅ 가능
INSERT INTO TABLE ✅ 자동 위치 삽입 ✅ 가능
READ 성능 ✅ O(log n) ✅ O(log n)
LOOP WHERE 성능 ✅ 부분탐색 ✅ USING KEY 지정 시
메모리 추가 사용 없음 ✅ 인덱스만큼 추가
중복 제어 UNIQUE/NON-UNIQUE NON-UNIQUE만 가능

5. 실무에서 헷갈리는 케이스

" -------------------------------------------------------
" 케이스 1: SELECT INTO SORTED TABLE
" -------------------------------------------------------
DATA lt_sorted TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY matnr.

" DB ORDER BY 없어도 INSERT 시 자동 정렬
SELECT * FROM /scwm/aqua
  INTO TABLE @lt_sorted    " ✅ matnr 기준 자동 정렬됨
  WHERE lgnum = '1710'.

" -------------------------------------------------------
" 케이스 2: SORTED TABLE에 SORT 문 사용
" -------------------------------------------------------
SORT lt_sorted BY matnr.  " ⚠️ 이미 정렬되어 있어 불필요
                            " 심지어 KEY 순서와 다르면 에러!

" -------------------------------------------------------
" 케이스 3: Secondary Key - LOOP 결과 차이
" -------------------------------------------------------
DATA lt_std TYPE STANDARD TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY primary_key COMPONENTS lgpla
  WITH NON-UNIQUE SORTED KEY sk_mat COMPONENTS matnr.

" ❌ USING KEY 없이 WHERE만 → 전체탐색 + 입력순 출력
LOOP AT lt_std INTO DATA(ls) WHERE matnr = 'X'.
ENDLOOP.

" ✅ USING KEY 지정 → Binary Search + 정렬순 출력
LOOP AT lt_std INTO DATA(ls)
  USING KEY sk_mat WHERE matnr = 'X'.
ENDLOOP.

6. 선택 가이드

"정렬된 데이터가 필요해"
        │
        ├─ 데이터 자체가 항상 정렬되어야 함
        │   + READ/LOOP 모두 정렬 순서 보장 필요
        │           └─→ SORTED TABLE ✅
        │
        └─ APPEND 순서는 유지하되
            특정 키로 빠른 READ/LOOP만 필요
                    └─→ Secondary SORTED KEY ✅
 

한 줄 요약:

SORTED TABLE = 데이터 자체가 정렬 Secondary SORTED KEY = 인덱스만 정렬, 데이터는 그대로

 

Sorted Table - 반드시 정렬이 목적일 필요는 없다

SORTED TABLE의 진짜 가치는

정렬 그 자체가 아니라
 LOOP WHERE 부분탐색 (Binary Search 자동 적용) 이다!
 

비교로 이해하기

" 같은 데이터, 같은 조건으로 LOOP
DATA lt_standard TYPE STANDARD TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY matnr.

DATA lt_sorted TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY matnr.        " 동일 KEY

" 둘 다 동일하게 SELECT
SELECT * FROM /scwm/aqua INTO TABLE @lt_standard WHERE lgnum = '1710'.
SELECT * FROM /scwm/aqua INTO TABLE @lt_sorted   WHERE lgnum = '1710'.

" -------------------------------------------------------
" STANDARD TABLE LOOP
" -------------------------------------------------------
LOOP AT lt_standard INTO DATA(ls)
  WHERE matnr = 'MAT-001'.
  " 👉 10만 건 전체를 처음부터 끝까지 스캔 O(n)
ENDLOOP.

" -------------------------------------------------------
" SORTED TABLE LOOP  ← 정렬 '결과'가 필요 없어도!
" -------------------------------------------------------
LOOP AT lt_sorted INTO DATA(ls)
  WHERE matnr = 'MAT-001'.
  " 👉 Binary Search로 해당 구간만 탐색 O(log n) ✅
  " 👉 조건 벗어나는 순간 자동 LOOP 종료
ENDLOOP.
 

SORTED TABLE LOOP 내부 동작

STANDARD TABLE (10만건)
┌────┬────┬────┬────┬─ ··· ─┬────┐
│ C  │ A  │ D  │ B  │  ...  │ Z  │  ← 전체 스캔
└────┴────┴────┴────┴─ ··· ─┴────┘
  ↑ 처음부터                    ↑ 끝까지 (조건 불일치도 계속)

SORTED TABLE (10만건, matnr 정렬)
┌────┬────┬────┬─────────────┬────┬────┐
│ A  │ A  │ B  │ [MAT-001들] │ C  │ D  │
└────┴────┴────┴─────────────┴────┴────┘
              ↑ Binary Search로           ↑ 여기서 자동 STOP
                바로 이 구간으로 점프

실무에서 정렬 순서가 필요 없는데 SORTED TABLE 쓰는 패턴

패턴 1: 대용량 필터링 - 순서 무관

" 목적: 특정 자재의 재고만 빠르게 꺼내기
" 정렬 순서: 관심 없음

DATA lt_stock TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY lgnum matnr.  " 성능용 KEY

SELECT * FROM /scwm/aqua
  INTO TABLE @lt_stock
  WHERE lgnum = '1710'.

" 정렬된 순서로 출력될 필요 없음
" 그냥 matnr = 'X' 인 것만 빠르게 가져오면 됨
LOOP AT lt_stock INTO DATA(ls)
  WHERE lgnum = '1710'
    AND matnr = 'MAT-001'.   " ✅ Binary Search 자동 적용
  " 처리 로직
ENDLOOP.
 
패턴 2: LOOP 안의 LOOP 최적화
" 외부: ORDIM_O 루프
" 내부: AQUA에서 매칭 찾기 → 이게 느린 포인트

" ❌ 느린 방식
DATA lt_aqua_std TYPE STANDARD TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY lgpla matnr.

LOOP AT lt_ordim INTO DATA(ls_ordim).
  LOOP AT lt_aqua_std INTO DATA(ls_aqua)   " O(n) 매번 전체탐색
    WHERE lgpla = ls_ordim-vlpla
      AND matnr = ls_ordim-matnr.
  ENDLOOP.
ENDLOOP.
" 전체: O(n²) 💀

" ✅ SORTED TABLE으로 개선
DATA lt_aqua_srt TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY lgpla matnr.   " 순서 필요 없음, 성능만!

LOOP AT lt_ordim INTO DATA(ls_ordim).
  LOOP AT lt_aqua_srt INTO DATA(ls_aqua)   " O(log n) 부분탐색
    WHERE lgpla = ls_ordim-vlpla
      AND matnr = ls_ordim-matnr.
  ENDLOOP.
ENDLOOP.
" 전체: O(n log n) ✅
 
패턴 3: READ TABLE 대안
" HASHED TABLE 못 쓰는 상황 (NON-UNIQUE KEY)
" → SORTED TABLE이 차선책

" 중복 가능한 키인데 빠른 READ가 필요할 때
DATA lt_wt TYPE SORTED TABLE OF /scwm/ordim_o
  WITH NON-UNIQUE KEY matnr charg.  " 중복 가능 → HASHED 불가

" Binary Search로 첫 번째 매칭 레코드 접근
READ TABLE lt_wt
  WITH KEY matnr = 'MAT-001'
           charg = 'BATCH-01'
  INTO DATA(ls_wt).                 " O(log n) ✅
 

SORTED TABLE 사용 판단 기준

내 상황은?
    │
    ├─ 출력/처리 순서가 중요하다
    │       └─→ SORTED TABLE (정렬 목적 O)
    │
    ├─ 순서는 필요 없지만
    │   LOOP WHERE로 대량 필터링을 자주 한다
    │       └─→ SORTED TABLE (성능 목적 ✅)
    │
    ├─ 단건 READ만 하고 키 중복이 없다
    │       └─→ HASHED TABLE (더 빠름)
    │
    └─ APPEND가 많고 READ는 가끔이다
            └─→ STANDARD TABLE
 

한 줄 요약

SORTED TABLE은 정렬이 부산물이고,
LOOP WHERE 부분탐색이 진짜 목적이다.
정렬 순서가 필요 없어도
대량 데이터 필터링 성능이 필요하다면 적극 활용하세요!

SORTED TABLE - 정렬 순서가 반드시 필요한 사용 사례

사례 1: LOOP AT GROUP (그룹 집계)

" 정렬이 보장되어야 GROUP이 정확히 동작함
DATA lt_stock TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY matnr charg.  " matnr 기준 정렬 보장

" ✅ 동일 matnr끼리 연속으로 모여있어서 GROUP이 정확함
LOOP AT lt_stock INTO DATA(ls)
  GROUP BY ( matnr = ls-matnr )
  ASSIGNING FIELD-SYMBOL(<grp>).

  DATA(lv_total) = CONV /scwm/de_menge_puom( 0 ).
  LOOP AT GROUP <grp> INTO DATA(ls_item).
    lv_total += ls_item-quan.
  ENDLOOP.

  WRITE: / <grp>-matnr, lv_total.
ENDLOOP.

" ❌ STANDARD TABLE이면?
" A, C, A, B, A 처럼 섞여서 → A 그룹이 3개로 쪼개짐!

사례 2: AT NEW / AT END (구간 처리)

" 고전적 패턴이지만 현장에서 여전히 많이 사용
DATA lt_wt TYPE SORTED TABLE OF /scwm/ordim_o
  WITH NON-UNIQUE KEY matnr lgpla.

LOOP AT lt_wt INTO DATA(ls_wt).

  AT NEW matnr.                  " ✅ 정렬 보장되어야 의미있음
    WRITE: / '=== 자재 시작:', ls_wt-matnr.
    DATA(lv_sum) = CONV /scwm/de_menge_puom( 0 ).
  ENDAT.

  lv_sum += ls_wt-anfme.

  AT END OF matnr.               " ✅ 마지막 행 감지
    WRITE: / '소계:', lv_sum.
  ENDAT.

ENDLOOP.

" STANDARD TABLE이면 AT NEW/END 가 중간에 오락가락
" A, C, A → AT NEW matnr 이 A에서 두 번 발생!

사례 3: 선입선출 (FIFO) 재고 처리

" 입고일 기준 오래된 것부터 출고
DATA lt_fifo TYPE SORTED TABLE OF /scwm/aqua
  WITH NON-UNIQUE KEY matnr charg lgpla.

" CHARG(배치)에 입고일이 인코딩된 경우
" 또는 별도 입고일 필드 기준 정렬

SELECT a~matnr, a~charg, a~lgpla, a~quan,
       b~hsdat AS inbound_date    " 입고일
  FROM /scwm/aqua AS a
  JOIN mch1 AS b
    ON b~matnr = a~matnr
   AND b~charg = a~charg
  INTO CORRESPONDING FIELDS OF TABLE @lt_fifo
  WHERE a~lgnum = '1710'
  ORDER BY b~hsdat ASCENDING.    " 오래된 배치부터

" 정렬 보장 → 위에서부터 순서대로 출고 처리
DATA(lv_remain) = CONV /scwm/de_menge_puom( 100 ).  " 출고 필요량

LOOP AT lt_fifo INTO DATA(ls_fifo).
  IF lv_remain <= 0. EXIT. ENDIF.

  DATA(lv_pick) = MIN( ls_fifo-quan, lv_remain ).
  lv_remain -= lv_pick.

  WRITE: / '출고 Bin:', ls_fifo-lgpla,
           '배치:', ls_fifo-charg,
           '수량:', lv_pick.
ENDLOOP.

 

사례 4: 범위 비교 / 임계값 처리
" Bin 위치 코드 순서대로 순차 처리
" 예: ZONE-A-001 → ZONE-A-002 → ZONE-B-001 순으로 피킹

DATA lt_bins TYPE SORTED TABLE OF /scwm/lgpla
  WITH UNIQUE KEY lgnum lgpla.   " lgpla 알파벳 정렬 보장

" 특정 구역 이후 Bin만 처리
LOOP AT lt_bins INTO DATA(ls_bin)
  WHERE lgnum = '1710'
    AND lgpla >= 'ZONE-B'.      " ✅ 정렬 보장이어야 >= 가 의미있음
  WRITE: / ls_bin-lgpla.
ENDLOOP.

" ❌ STANDARD TABLE이면
" ZONE-C, ZONE-A, ZONE-B 섞여서
" >= 'ZONE-B' 조건이 올바른 범위를 보장 못함

사례 5: 중복 제거 (UNIQUE KEY 활용)

" UNIQUE KEY → 중복 INSERT 시 자동 차단
" 데이터 정합성을 테이블 선언 레벨에서 보장

DATA lt_processed TYPE SORTED TABLE OF /scwm/tanum_t
  WITH UNIQUE KEY tanum.         " 동일 WT 중복 처리 방지

LOOP AT lt_ordim INTO DATA(ls_ordim).

  " 이미 처리된 WT면 INSERT 실패 → 중복 처리 방지
  INSERT VALUE #( tanum = ls_ordim-tanum )
    INTO TABLE lt_processed.

  IF sy-subrc <> 0.
    CONTINUE.                    " 중복 → 스킵
  ENDIF.

  " 신규 WT만 처리
  PERFORM process_wt USING ls_ordim.

ENDLOOP.

사례 6: 출력 보고서 (순서 보장)

" ALV / 출력 레포트에서 정렬된 순서 보장
DATA lt_report TYPE SORTED TABLE OF ty_report
  WITH NON-UNIQUE KEY werks matnr.

" SELECT 시 ORDER BY 없어도
" 테이블에 담기는 순간 자동 정렬
SELECT werks, matnr, lgpla, quan
  FROM /scwm/aqua
  INTO CORRESPONDING FIELDS OF TABLE @lt_report
  WHERE lgnum = '1710'.

" ALV 출력 → 항상 werks → matnr 순으로 표시 보장
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
  EXPORTING it_outtab = lt_report.

정리

사례 이유
LOOP AT GROUP 같은 키 값이 연속해야 그룹이 올바르게 묶임
AT NEW / AT END 구간 전환 감지가 정렬 순서에 의존
FIFO 재고처리 오래된 것부터 순서대로 소진해야 함
범위 조건 (>=, <=) 정렬 보장 없으면 범위 의미가 없음
중복 제거 UNIQUE KEY로 삽입 시점에 정합성 강제
보고서 출력 사용자에게 보여주는 순서 보장
핵심: 단순 성능이 아니라 "순서에 의존하는 로직" 이 있다면 SORTED TABLE의 자동 정렬이 버그 방지 역할까지 합니다!
 


 

반응형