ABAP

아직도 상관 서브쿼리? LATERAL JOIN으로 #shorts #SAP #ABAP

▶ YouTube에서 보기

상관 서브쿼리의 성능 문제

ABAP Open SQL에서 상관 서브쿼리(Correlated Subquery)는 외부 쿼리의 각 행마다 내부 쿼리를 반복 실행합니다. 결과 집합이 수만 건이라면 데이터베이스에 수만 번의 서브쿼리가 실행되어 성능이 급격히 나빠집니다. SAP HANA 2.0 SPS 04 이후부터 지원하는 LATERAL JOIN은 이 문제를 해결합니다.

상관 서브쿼리 예제 — 문제 상황

" 각 고객별 최근 주문 1건 조회 — 상관 서브쿼리 방식
SELECT cust.customer_id,
       cust.customer_name,
       ( SELECT TOP 1 ord.order_date
         FROM zbtp_sales_order AS ord
         WHERE ord.customer_id = cust.customer_id
         ORDER BY ord.order_date DESCENDING ) AS last_order_date
  FROM zbtp_customer AS cust
  INTO TABLE @DATA(lt_result).

이 쿼리는 zbtp_customer 테이블의 행 수만큼 zbtp_sales_order 서브쿼리가 실행됩니다. 고객이 10만 명이면 서브쿼리가 10만 번 실행됩니다.

LATERAL JOIN으로 동일 결과를 효율적으로

" LATERAL JOIN 방식 — HANA 2.0 SPS04+ 필요
SELECT cust.customer_id,
       cust.customer_name,
       last_ord.order_date AS last_order_date,
       last_ord.order_amount
  FROM zbtp_customer AS cust
  CROSS JOIN LATERAL (
    SELECT TOP 1 ord.order_date, ord.order_amount
    FROM zbtp_sales_order AS ord
    WHERE ord.customer_id = cust.customer_id
    ORDER BY ord.order_date DESCENDING
  ) AS last_ord
  INTO TABLE @DATA(lt_result).

LATERAL JOIN은 외부 쿼리의 컬럼을 참조하는 서브쿼리를 JOIN처럼 사용합니다. HANA 옵티마이저가 전체 쿼리를 한 번의 실행 계획으로 최적화하므로 상관 서브쿼리보다 훨씬 빠릅니다.

LEFT OUTER JOIN LATERAL — 데이터 없는 고객 포함

주문이 없는 고객도 결과에 포함시키려면 LEFT OUTER JOIN LATERAL을 사용합니다.

SELECT cust.customer_id,
       cust.customer_name,
       last_ord.order_date     AS last_order_date,
       last_ord.order_amount   AS last_order_amount
  FROM zbtp_customer AS cust
  LEFT OUTER JOIN LATERAL (
    SELECT TOP 1 ord.order_date, ord.order_amount
    FROM zbtp_sales_order AS ord
    WHERE ord.customer_id = cust.customer_id
    ORDER BY ord.order_date DESCENDING
  ) AS last_ord ON 1 = 1
  INTO TABLE @DATA(lt_result).

주문이 없는 고객의 경우 last_order_datelast_order_amount는 초기값(공백/0)으로 채워집니다.

LATERAL JOIN으로 집계값 가져오기

각 부서별 직원 수와 평균 급여를 구하면서 부서 정보도 함께 조회하는 경우:

SELECT dept.department_id,
       dept.department_name,
       dept.budget,
       stats.headcount,
       stats.avg_salary
  FROM zbtp_department AS dept
  CROSS JOIN LATERAL (
    SELECT COUNT(*) AS headcount,
           AVG( emp.salary ) AS avg_salary
    FROM zbtp_employee AS emp
    WHERE emp.department_id = dept.department_id
      AND emp.active = 'X'
  ) AS stats
  INTO TABLE @DATA(lt_dept_stats).

GROUP BY 없이 각 부서에 대한 집계를 한 쿼리로 얻습니다.

CDS View에서 LATERAL JOIN 활용

define view ZI_CustomerLastOrder
  as select from zbtp_customer as Cust
    cross join lateral (
      select top 1
             order_date,
             order_amount,
             customer_id as cid
      from zbtp_sales_order
      where customer_id = Cust.customer_id
      order by order_date descending
    ) as LastOrd
{
  key Cust.customer_id,
      Cust.customer_name,
      LastOrd.order_date  as last_order_date,
      LastOrd.order_amount as last_order_amount
}

CDS View에서도 LATERAL JOIN 문법을 그대로 사용할 수 있습니다.

LATERAL JOIN 사용 전 확인사항

  • SAP HANA 2.0 SPS 04 이상 또는 HANA Cloud 필요
  • BTP ABAP Environment에서는 기본 지원
  • On-Premise S/4HANA 2022 이상에서 사용 가능
  • CROSS JOIN LATERAL은 매칭되는 행이 반드시 있어야 함 (없으면 해당 외부 행 제외)
  • LEFT OUTER JOIN LATERAL ON 1=1은 매칭 없어도 외부 행 유지

공식 문서

ABAP Open SQL의 LATERAL JOIN 문법은 SAP ABAP CDS 공식 문서와 ABAP Keyword Documentation의 SELECT 문법 섹션에서 확인할 수 있습니다.

댓글 0

아직 댓글이 없습니다.