반응형
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 → 정렬 안됨! 조회 최적화만 ✅
" 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의 자동 정렬이 버그 방지 역할까지 합니다!
반응형