본문 바로가기
SAP Story/CDS View

DDL정의(2) View 정의 - 데이터 집계(Select)- data_source( Join )

by 돈보따리 2022. 11. 23.
반응형

데이터 집계와 관련한 주제 중 Data_source 중에서 Join을 사용하는 방법에 대해서 알아보도록 하겠습니다.

 


문법

... { [INNER] JOIN }|{ LEFT|RIGHT OUTER [TO ONE|MANY] JOIN }|{ CROSS JOIN }
       data_source [ON cond_expr] ...

 

효과

CDS View의 두 개의 Data Source 사이의 Join(결합)을  정의합니다. 위의 코드는 데이터소스 data_source 구문의 일부이고 데이터 소스 data_source의 재귀 구문을 포함합니다. 결합 식(join expression)을 생성한 JOIN을 사용하여 두 데이터 소스를 결합합니다. 결합 식은 INNER 또는 OUTER를 사용합니다. 결합조건 cond_expr 는 ON 구문 뒤에 반드시 정의되어야 합니다. 이 조건이 지정되면 특별한 규칙이 적용됩니다. CROSS를 사용한 결합 식에는 결합조건을 지정할 수 없습니다.

 

INNER JOIN, OUTER JOIN, CROSS 모두 가능 합니다.

  ■ INNER JOIN을 사용하거나 JOIN만을 사용한 두 데이터 소스의 join은 ON 조건의 필드가 일치하는 모든 데이터 소스 리스트를 선택(select)합니다.

  ■ LEFT OUTER JOIN을 사용한 두 데이터 소스의 join은 왼쪽 테이블의 모든 데이터를 선택(select)합니다. RIGHT OUTER JOIN을 사용한 두 데이터 소스의 join은 오른쪽 테이블의 모든 데이터를 선택(select)합니다. ON 조건으로 일치하는 데이터는 inner join과 동일한 결과입니다. ON 조건으로 일치하지 않는 데이터에 대한 Left 또는 Right 의 값들은 null 값으로 리턴합니다. Open SQL 에서 CDS View를 사용할 때에는 필드 유형에 해당하는 initial 값으로 리턴합니다.

  ■ CROSS JOIN을 사용하여 두 데이터 소스를 결합할 때, 두 데이터 소스간에 교차 데이터 소스가 생성됩니다. 왼쪽의 모든 값과 오른쪽의 모든 값이 결합됩니다. 이 결과값의 항목 수는 [왼쪽의 항목 수 X 오른쪽의 항목 수] 입니다.

 

중첩된 결합 식은 다음 순서로 적용됩니다.

  ■ inner join 또는 outer join 의 경우는 ON 조건의 순서로 적용됩니다. 왼쪽에서 오른쪽으로, 가장 인접한 ON 조건이 JOIN에 할당되고 이 표현식은 암묵적으로 괄호로 묶입니다. 이러한 암묵적인 괄호는 실제 괄호 ( ) 를 사용하여 명시적으로 만들 수 있습니다. 괄호 표기는 필수는 아니고 선택적으로 적용합니다. 

  ■ 기본적으로 Cross join은 왼쪽에서 오른쪽으로 평가됩니다. 평가의 우선순위는 괄호( ) 에 의해 영향을 받을 수 있습니다.

      - 여러 Cross Join이 결합된 경우 평가 순서는 무의미합니다. 결과는 항상 동일하고, 행 수는 모든 데이터 소스의 행 수를 곱한 값 입니다.

      - Cross Join 이 Inner Join 및 Outer Join과 결합된 경우, 결과는 평가 순서 또는 괄호에 따라 달라질 수 있습니다.

 

 

메모

  ■ Join에서 Select 구문에 대한 Where 조건은 join을 사용한 결과 세트에 적용됩니다.

  ■ 두 개의 개별적인 데이터 소스간의 inner join 또는 cross join 은 교환 가능합니다. 왼쪽과 오른쪽의 데이터 소스의 위치가 바뀌어도 결과값은 동일합니다.

  ■ Outer Join을 포함한 CDS View의 버퍼링은 권장하지 않습니다. 결과 값에 Null 값이 포합될 수 있습니다. 즉, 버퍼의 Null 값이 initial 값으로 변환되기 때문에 Open SQL에서 읽는 경우 버퍼를 읽을 때 데이터베이스를 직접 읽는 것과 다르게 동작할 수 있습니다.

  ■ 함수 coalesce(병합)를 사용하여 결과 집합에서 null 값을 방지할 수 있습니다.

  ■ Cross Join은 ON 조건이 항상 True 인 inner 또는 outer join 처럼 동작합니다. Where 조건이 포함된 Cross Join은 동일한 ON 조건이 포함된 inner join과 동일한 결과를 가집니다. Inner Join과 달리 Cross Join에서는 조건이 적용되기 전에 모든 데이터를 읽습니다. Inner Join에서는 ON 조건에 적용되는 데이터만 읽습니다.

  ■ Cross Join은 매우 주의해서 사용해야 합니다. ON 조건을 적용할 수 없기 때문에 데이터 소스에 포함된 모든 데이터를 읽습니다. 매우 큰 사이즈의 데이터셋의 경우 결과 값이 매우 커질 수 있습니다.(행 수는 항상 두 데이터 소스의 모든 행수의 곱)

  ■ 데이터베이스에서 두 클라이언트별 데이터 소스의 Cross Join은 Inner Join으로 정의됩니다. ON 조건은 왼쪽과 오른쪽의 클라이언트 열이 같은지 확인합니다. 한쪽이 클라언트별 지정이 아닌 경우, Cross Join이 지정된 대로 정의됩니다.

  ■ 중첩된 결합식에서는 코드를 더 쉽게 읽을 수 있도록 괄호를 사용하는 것이 좋습니다. inner join 및 outer join의 경우 ON 조건에서 암묵적으로 괄호를 지정하는 모든 위치에 괄호를 지정할 수 있습니다.

  ■ DDL에서 CDS View의 Select 구문에서 결합식의 개수는 제한이 없습니다. 하지만 특정 수의 표현식에 도달하면 메시지를 생성하는 ATC 검사가 있습니다.

 


예시

다음 CDS View는 데이터베이스 뷰 DEMO_SCARR_SPFLI와 동일한 방식으로 작동합니다. 프로그램 DEMO_CDS_JOIN 는 이 View를 Select 하는 프로그램입니다. 데이터베이스 뷰 DEMO_SCARR_SPFLI 에 접근하는 것과 다르게, CDS View 엔터티 DEMO_CDS_SCARR_SPFLI 에 접근하면 클라이언트 컬럼이 리턴되지 않습니다. CDS 데이터베이스 View인 DEMO_CDS_JOIN 는 클라이언트 컬럼을 리턴하지 않습니다.

@AbapCatalog.sqlViewName: 'DEMO_CDS_JOIN'
@AccessControl.authorizationCheck: #NOT_ALLOWED
define view demo_cds_scarr_spfli(
    id,
    carrier,
    flight,
    departure,
    destination
  )
  as select from
           spfli
      join scarr on
        scarr.carrid = spfli.carrid
    {
      key spfli.carrid,
      key scarr.carrname,
      key spfli.connid,
          spfli.cityfrom,
          spfli.cityto
    }

REPORT demo_cds_join.

CLASS demo DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS main.
ENDCLASS.

CLASS demo IMPLEMENTATION.
  METHOD main.
    SELECT *
           FROM demo_cds_scarr_spfli
           ORDER BY id, carrier, flight
           INTO TABLE @DATA(result).
    cl_demo_output=>display( result ).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  demo=>main( ).

 


예시

다음은 괄호로 묶이지 않은 결합식(join expressions)입니다.

... from tab1
      join
        tab2
          join
            tab3 on tab2.id = tab3.id
                 on tab1.id = tab2.id ...

이것을 명시적인 괄호를 반영했습니다.

... from tab1
      join
        ( tab2
            join
              tab3 on tab2.id = tab3.id ) on tab1.id = tab2.id ...

Inner Join ON 조건에서 tab1 의 요소를 지정할 수 없습니다.

 


예시

다음 View는 테이블 T100 의 메시지 클래스 SABAPDEMOS 에 대한 항목과 As ABAP의 모든 클라이언트 테이블 T000 의 Cross Join을 포함합니다. DEMO_CDS_CROSS_JOIN 프로그램은 이 View를 사용합니다. 이 Where 조건이 없다면 매우 큰 데이터 셋이 만들어 집니다.

@AbapCatalog.sqlViewName: 'DEMO_CDS_CRSJN'
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view demo_cds_cross_join
  as select from
                 t000
      cross join t100
    {
      t000.mandt,
      t000.mtext,
      t100.sprsl,
      t100.arbgb,
      t100.msgnr,
      t100.text
    }
    where
      t100.arbgb = 'SABAPDEMOS'    

REPORT demo_cds_cross_join.

CLASS demo DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS main.
ENDCLASS.

CLASS demo IMPLEMENTATION.
  METHOD main.
    SELECT *
           FROM demo_cds_cross_join
           INTO TABLE @DATA(itab)
           ORDER BY mandt, sprsl, msgnr.
    cl_demo_output=>display( itab ).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  demo=>main( ).

 


추가 기능

... TO ONE|MANY

효과

Left Outer Join 의 카디날리티( cardinality, 수 )를 지정합니다. 이 추가 부분은 LEFT OUTER 다음에 위치합니다. RIGHT OUTER 에는 사용할 수 없습니다. 특정 데이터베이스 시스템만 이 추가 부분을 적용합니다.

TO ONE 또는 TO MANY 를 추가하여 지정하면, 이 추가를 지원하는 모든 데이터베이스는 왼쪽의 Outer Join 에 의해 정의된 결과 집합이 이 카디널리티와 일치한다고 가정하고 SQL Optimizer는 추가적인 Join을 억제하려고 시도합니다. 결과값이 카디널리티와 일치하지 않으면 결과는 정의되지 않으며, Select 목록의 항목에 따라 달라질 수 있습니다.

 

메모

  ■ 더 자세한 내용은 현재 데이터베이스 시스템의 설명서에서 확인 할 수 있습니다. 예를들어 SAP HANA 데이터베이스의 경우 TO ONE 또는 TO MANY 를 지원하고, HANA-Specific SQL 문서에서 확인할 수 있습니다

  ■ 정의되지 않은 플랫폼별 동작을 장지하기 위해 읽는 데이터가 해당하는 과련 사전 요구 사항을 충족하는 경우에만 TO ONE 또는 TO MANY를 지정할 수 있습니다.

 

예시

CDS View에서 TO ONE을 잘못사용했습니다. 데이터베이스 테이블 SCARR과 SPFLI는 TO ONE 의 카디널리티를 가지지 않고 대신해서 TO MANY에 해당하는 카디널리티를 가지고 있습니다. 예를들어 SAP HANA 데이터베이스의 경우 결과는 Select 목록에 따라 달라집니다. 여기에서 왼쪽 및 오른쪽을 지정하면 최적화가 수행되지 않습니다. 오른쪽의 컬럼이 지정되니 않은 경우( count(*) 집계 펑션을 사용 ), 최적화가 수행됩니다. 여기에서는 전제 조건 카디널리티를 충족하는 데이터만 읽습니다.

 

@AbapCatalog.sqlViewName: 'DEMOCDSWTO1'
define view demo_cds_wrong_to_one_1
  as select from
                             scarr as c
      left outer to one join spfli as p on
        c.carrid = p.carrid
    {
      c.carrid   as carrid,
      c.carrname as carrname,
      p.connid   as connid
    }
@AbapCatalog.sqlViewName: 'DEMOCDSWTO2'
define view demo_cds_wrong_to_one_2
  as select from
                             scarr as c
      left outer to one join spfli as p on
        c.carrid = p.carrid
    {
      c.carrid   as carrid,
      c.carrname as carrname
    }
@AbapCatalog.sqlViewName: 'DEMOCDSWTO3'
define view demo_cds_wrong_to_one_3
  as select from
                             scarr as c
      left outer to one join spfli as p on
        c.carrid = p.carrid
    {
      count(*) as cnt
    }

프로그램 DEMO_CDS_WRONG_TO_ONE 는 위 CDS View에 접근하여 결과를 나타냅니다.

 

REPORT demo_cds_wrong_to_one.

CLASS demo DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS main.
ENDCLASS.

CLASS demo IMPLEMENTATION.
  METHOD main.
    DATA(outcl_demo_output=>new).

    out->next_section`Fields of left and right table` ).
    SELECT FROM demo_cds_wrong_to_one_1
           FIELDS *
           ORDER BY carrid
           INTO TABLE @DATA(itab).
    out->writeitab ).
    out->writesy-dbcnt ).

    out->next_section`Fields of left table only` ).
    SELECT FROM demo_cds_wrong_to_one_2
           FIELDS *
           ORDER BY carrid
           INTO CORRESPONDING FIELDS OF TABLE @itab.
    out->writeitab ).
    out->writesy-dbcnt ).

    out->next_section`COUNT(*)` ).
    SELECT SINGLE
           FROM demo_cds_wrong_to_one_3
           FIELDS *
           INTO @DATA(count).
    out->writecount ).

    out->display).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  demo=>main).

 


■ ABAP CDS - SELECT, data_source
       - ABAP CDS - SELECT, parameters
       - ABAP CDS - SELECT, JOIN
  ■ ABAP CDS - SELECT, ASSOCIATION
       - ABAP CDS - path_expr
             :: ABAP CDS - path_expr, attributes
             ::  ABAP CDS - Joins of Associations
  ■ ABAP CDS - SELECT, select_list
       - ABAP CDS - SELECT, element
       - ABAP CDS - SELECT, element_annot
  ■ ABAP CDS- SELECT, clauses
       - ABAP CDS - SELECT, WHERE
       - ABAP CDS - SELECT, GROUP BY
       - ABAP CDS - SELECT, HAVING
       - ABAP CDS - SELECT, UNION
  ■ ABAP CDS - SELECT, Operands and Expressions
       - ABAP CDS - literal
       - ABAP CDS - field
       - ABAP CDS - parameter
       - ABAP CDS - session_variable
       - ABAP CDS - arith_expr
       - ABAP CDS - aggr_expr
       - ABAP CDS - case_expr
       - ABAP CDS - cast_expr
       - ABAP CDS - cond_expr
  ■ ABAP CDS - SELECT, Built-In Functions
       - ABAP CDS - sql_functions
              - ABAP CDS - Numeric Functions
              - ABAP CDS - String Functions
              - ABAP CDS - coalesce
       - ABAP CDS - Special Functions
              - ABAP CDS - Conversion Functions
                    - ABAP CDS - Type Conversion Functions
                    - ABAP CDS - Conversion Functions for Units and Currencies
              - ABAP CDS - Date Functions and Time Functions
                   - ABAP CDS - Date Functions
                    - ABAP CDS - Time Functions
                    - ABAP CDS - Time Stamp Functions
                    - ABAP CDS - Time Zone Functions
                    - ABAP CDS - Date/Time Conversions

반응형

댓글