콘텐츠
ABAP Open SQL 도 다른 SQL 과 같이 JOIN 문을 제공 해 두 테이블을 함께 조회 할 수 있다. 오늘은 JOIN 의 기본적인 사용 법과 유형들을 정리 해보자.
JOIN 문의 기본 구조
SELECT [DISTINCT] <필드 리스트>
FROM <테이블1> [AS] <별칭1>
[INNER | LEFT OUTER | RIGHT OUTER] JOIN <테이블2> [AS] <별칭2>
ON <별칭1>.<필드명1> = <별칭2>.<필드명2>
[WHERE 조건]
[INTO <내부 테이블>]
[ORDER BY <필드명>].
ABAP- [INNER | LEFT OUTER | RIGHT OUTER] JOIN: 조인 유형으로 결과 값이 달라진다. 아래에서 상세하게 다룬다.
- ON: ON 은 결합할 필드를 적는다. 대부분 두 테이블의 키 값을 서로 결합 하게 된다.
- 필드 리스트 또한 “별칭.필드” 를 적어 어느 테이블의 필드의 값을 가져올 지 정한다. (한쪽에만 있는 필드는 별칭이 없어도 문제는 없다.)
INNER JOIN
두 테이블에서 ON 으로 결합한 필드의 값이 서로 일치하여 존재할 경우에만 결과가 출력 되는 코드다. 다음 SFLIGHT 와 SCARR 테이블은 각각 항공편, 항공사 이름을 지닌 테이블로 carrid(항공 ID) 의 KEY 필드를 둘 다 지니고 있다.
다음 코드를 통해 각 테이블 내역을 조회해 보자.
DATA: lt_table TYPE TABLE OF sflight,
ls_table TYPE sflight.
SELECT a~carrid
b~carrname
a~connid
a~fldate
INTO CORRESPONDING FIELDS OF TABLE lt_table
FROM sflight
WHERE carrid = 'TE'
OR carrid = 'UA'
OR carrid = 'SQ'.
WRITE: /(20)'carrid',
(20)'connid',
(20)'fldate'.
LOOP AT lt_table INTO ls_table.
WRITE: / ls_table-carrid UNDER 'carrid',
ls_table-connid UNDER 'connid',
ls_table-fldate UNDER 'fldate'.
ENDLOOP.
ABAPDATA: lt_scarr TYPE TABLE OF scarr,
ls_scarr TYPE scarr.
SELECT *
INTO CORRESPONDING FIELDS OF TABLE lt_scarr
FROM scarr.
WRITE: /(20)'carrid',
(20)'carrname'.
LOOP AT lt_scarr INTO ls_scarr.
WRITE: / ls_scarr-carrid UNDER 'carrid',
ls_scarr-carrname UNDER'carrname'.
ENDLOOP.
ABAP이렇게 두 테이블의 결과 값이 있을 때, SFLIGHT 의 결과에 SCARR 테이블의 항공사 이름(carrname) 를 붙여 출력하고 싶다면 JOIN 을 이용할 수 있는 것이다.
그럼 INNER JOIN 을 이용해서 한번 두 테이블을 결합해 보자.
TYPES: BEGIN OF ty_table,
carrid TYPE sflight-carrid,
carrname TYPE scarr-carrname,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
END OF ty_table.
DATA: lt_table TYPE TABLE OF ty_table,
ls_table TYPE ty_table.
SELECT *
INTO CORRESPONDING FIELDS OF TABLE lt_table
FROM sflight AS a INNER JOIN scarr AS b
ON a~carrid EQ b~carrid
WHERE a~carrid = 'TE'
OR a~carrid = 'UA'
OR a~carrid = 'SQ'.
WRITE: /(20)'carrid',
(20)'carrname',
(20)'connid',
(20)'fldate'.
LOOP AT lt_table INTO ls_table.
WRITE: / ls_table-carrid UNDER 'carrid',
ls_table-carrname UNDER 'carrname',
ls_table-connid UNDER 'connid',
ls_table-fldate UNDER 'fldate'.
ENDLOOP.
ABAP위의 코드를 보면 두 테이블의 별칭을 각각 a, b 로 정해 준 후 inner join 으로 결합하였다.
결합 할 기준 값은 같은 carrid ID 를 지닌 값으로 INTO CORRESPONDING FIELDS OF TABLE 로 Internal Table 인 lt_table 에 값이 잘 들어간 것을 알 수 있다.
그런데 보면, 위의 설명과 같이 ‘서로 일치 하는 값이 존재하는 경우’ 에만 출력 되는 INNER JOIN 의 특징으로 인해 sflight 에 carrid 가 ‘TE’ 인 행들이 출력 되지 않는다.
이런 경우 표시하고 싶다면 아래 LEFT OUTER JOIN 을 사용할 수 있다.
LEFT OUTER JOIN
LEFT OUTER JOIN 은 왼쪽의 테이블이 기준 테이블이 되고 조인한 테이블 에서 일치하는 내용을 읽어와 추가로 표시할 때 사용한다.
위의 INNER JOIN 에서 sflight 와 scarr 테이블을 조합 했을 때 ON 으로 조합한 필드의 값이 서로 동일한 게 존재 할 경우 행이 조회 되었지만, LEFT OUTER JOIN 은 sflight 의 값을 먼저 다 가져온 후, 일치하는 경우에만 추가로 scarr 을 표시 한다.
그래서 scarr 테이블에 없는 carrid 인 TE 값을 지닌 행들도 전부 출력 된다.
추가로, LEFT OUTER JOIN 에서는 기준 점이 된 sflight 테이블에만 where 조건을 넣을 수 있고 scarr은 불가능 하다.
TYPES: BEGIN OF ty_table,
carrid TYPE sflight-carrid,
carrname TYPE scarr-carrname,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
END OF ty_table.
DATA: lt_table TYPE TABLE OF ty_table,
ls_table TYPE ty_table.
SELECT a~carrid
b~carrname
a~connid
a~fldate
INTO CORRESPONDING FIELDS OF TABLE lt_table
FROM sflight AS a LEFT OUTER JOIN scarr AS b
ON a~carrid EQ b~carrid
WHERE a~carrid = 'TE'
OR a~carrid = 'UA'
OR a~carrid = 'SQ'.
WRITE: /(20)'carrid',
(20)'carrname',
(20)'connid',
(20)'fldate'.
LOOP AT lt_table INTO ls_table.
WRITE: / ls_table-carrid UNDER 'carrid',
ls_table-carrname UNDER 'carrname',
ls_table-connid UNDER 'connid',
ls_table-fldate UNDER 'fldate'.
ENDLOOP.
ABAPTE 는 carrname 이 scarr 테이블에 없으니까 공백으로 표시 되지만, INNER JOIN 과 다르게 행 자체는 조회가 된다.
RIGHT OUTER JOIN
LEFT OUTER JOIN 에선 왼쪽 테이블을 중심으로 값을 조회 했다면, RIGHT OUTER JOIN 은 우측에 온 테이블을 중심으로 값을 조회 하는 것이다. 그래서 위의 코드를 RIGHT OUTER JOIN 으로 변경 해 주면 이번엔 TE 값이 scarr 에 없으므로 출력 되지 않는다.
그런데, 이 코드를 활성화 하면서 특이한 점을 발견 했다. LEFT 를 RIGHT 로 바꾸니 필드를 쉼표(,) 로 구분하고 Internal Table 앞에 @를 붙이라는 오류 메시지가 출력된다.
@이는 7.40 버전 이상의 ABAP 에서 도입 되었으며 ABAP 내 선언 된 변수임을 표기하는 의미라고 한다. 그런데 왜 RIGHT OUTER JOIN 에서만 이런 현상이 발견 되는지는 알 수 없었다. 어쨌든, 오류 메시지를 해결하여 코드를 작성하면 다음과 같다.
TYPES: BEGIN OF ty_table,
carrid TYPE sflight-carrid,
carrname TYPE scarr-carrname,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
END OF ty_table.
DATA: lt_table TYPE TABLE OF ty_table,
ls_table TYPE ty_table.
SELECT b~carrid,
b~carrname,
a~connid,
a~fldate
INTO CORRESPONDING FIELDS OF TABLE @lt_table
FROM sflight AS a RIGHT OUTER JOIN scarr AS b
ON a~carrid = b~carrid
WHERE a~carrid = 'TE'
OR a~carrid = 'UA'
OR a~carrid = 'SQ'.
WRITE: /(20)'carrid',
(20)'carrname',
(20)'connid',
(20)'fldate'.
LOOP AT lt_table INTO ls_table.
WRITE: / ls_table-carrid UNDER 'carrid',
ls_table-carrname UNDER 'carrname',
ls_table-connid UNDER 'connid',
ls_table-fldate UNDER 'fldate'.
ENDLOOP.
ABAP