본문 바로가기
SAS/SAS Tip's

[데이터 결합] Data Step에서의 카테시안 곱(Cartesian product) 구현하기

by 기서무나구물 2021. 11. 16.

포스팅 목차

    [데이터 결합] Data Step에서의 카테시안 곱(Cartesian product) 구현하기



    교차 조인 (Cross Join) 은 말 그대로 두 개의 테이블을 그냥 붙였다는 개념이다. 아무런 조건이나 제한 사항 없이 양쪽은 있는 그대로 연결만 했다는 개념으로 생각을 하면 되겠다.
    쉽게 2개 기준 테이블에 존재하는 전체 관측치를 교차하여 결합하는 방식으로 생각해도 큰 무리가 없다.

     

    Cartesian product


    카테시안 곱은 두 개 이상의 기준 테이블에 대해 연결 가능한 행을 모두 결합하는 조인 방식. WHERE절에서 조인 조건절을 생략하거나 조인 조건을 잘못 설정하여 양쪽 테이블을 연결하는 조건을 만족하는 행이 하나도 없는 경우에 자주 발생한다. 카테시안 곱이 발생하면 각 테이블의 행의 수를 곱한 만큼의 조인 결과가 생성된다. 

    대용량의 테이블에서 카테시안 곱이 발생할 경우 SQL 명령문의 처리 속도가 현저하게 저하되므로 주의해야 한다.
    1,000 개의 관측치를 보유한 2개 테이블에 대하여 Cartesian product 이 발생하면 10,000 * 10,000 = 100,000,000 건이 출력이 된다.

    data BACK1; 
    input v1 $ v2; 
    cards; 
    a 1 
    a 2 
    a 3 
    b 4 
    b 5 
    ; 
    run;
    
    data BACK2; 
    input v1 $ v3; 
    cards; 
    a 12 
    a 13 
    a 14 
    b 12 
    b 13 
    b 14 
    b 15 
    c 12 
    c 13 
    ; 
    run;

    교차조인;

    2개 테이블의 관측치 사이가 서로 교차하여서 결합을 수행하는 관측카테시안 곱이 발생하여서  45개의 관측치(5*9)를 반환한다.

    SAS Statements
    proc sql;
      select *
      from   BACK1,BACK2;
    quit;

     

    Results
    OBS    v1    v2    v3
    
      1    a      1    12
      2    a      1    13
      3    a      1    14
      4    a      1    12
      5    a      1    13
      6    a      1    14
      7    a      1    15
      8    a      1    12
      9    a      1    13
    
    ---------------------
    
     34    b      4    15
     35    b      4    12
     36    b      4    13
     37    b      5    12
     38    b      5    13
     39    b      5    14
     40    b      5    12
     41    b      5    13
     42    b      5    14
     43    b      5    15
     44    b      5    12
     45    b      5    13

     

    교차조인(CROSS JOIN);

    위와 동일하게 45개의 관측치(5*9)를 반환한다.

    SAS Statements
    proc sql;
      select *
      from   BACK1 CROSS JOIN BACK2;
    quit;

     

    데이터 스텝에서 카테시안 곱(Cartesian Product) 수행하기;

    BACK1 테이블을 기준으로 BACK2 테이블을 조회하여서 카테시안 곱을 발생 시켜서 교차 결합 작업을 수행한다.

    SAS Statements
    data BACK3(drop=v11); 
     set BACK1; 
         do i=1 to TOT_OBS; 
            set BACK2 point=i nobs=TOT_OBS; 
            output; 
         end; 
    run;

     

    Results
    OBS    v1    v2    v3
    
      1    a      1    12
      2    a      1    13
      3    a      1    14
      4    a      1    12
      5    a      1    13
      6    a      1    14
      7    a      1    15
      8    a      1    12
      9    a      1    13
    
    --------------------
    
     35    b      4    12
     36    b      4    13
     37    b      5    12
     38    b      5    13
     39    b      5    14
     40    b      5    12
     41    b      5    13
     42    b      5    14
     43    b      5    15
     44    b      5    12
     45    b      5    13

     


    카테시안 곱(Cartesian Product) 결합 조건을 부여하여 조건을 만족하는 관측치 출력

     

    교차조인

    카테시안 곱으로 교차 결합(교차조인)을 수행 후 2개 테이블의 V1 변수가 동일한 경우에 해당하는 관측치를 출력한다.

    SAS Statements
    proc sql;
      select *
      from   BACK1 A,BACK2 B
      WHERE  A.V1 = B.V1;
    quit;

     

    Results
    OBS    v1    v2    v3
    
      1    a      1    12
      2    a      3    12
      3    a      2    12
      4    a      1    13
      5    a      3    13
      6    a      2    13
      7    a      1    14
      8    a      3    14
      9    a      2    14
     10    b      4    12
     11    b      5    12
     12    b      4    13
     13    b      5    13
     14    b      4    14
     15    b      5    14
     16    b      4    15
     17    b      5    15

     

    교차조인(CROSS JOIN);

    위와 동일한 결과를 산출한다.

    SAS Statements
    proc sql;
      select *
      from   BACK1 A CROSS JOIN BACK2 B
      WHERE  A.V1 = B.V1;
    quit;

     

    데이터 스텝에서 카테시안 곱(Cartesian Product);

    BACK1 테이블을 기준으로 BACK2 테이블을 조회하여서 교차 결합(교차조인)을 수행 후 2개 테이블의 V1 변수가 동일한 경우에 해당하는 관측치를 출력한다. 양쪽 테이블의 V1 변수를 비교하기 위하여 BACK2 테이블의 V1 변수명을 V11으로 변경(RENAME) 후 비교 작업을 수행한다.

    SAS Statements
    data BACK4(drop=v11); 
     set BACK1; 
         do i=1 to TOT_OBS; 
            set BACK2 (rename=(v1=v11)) point=i nobs=TOT_OBS; 
            if v1=v11 then output; 
         end; 
    run;

     

    Results
    OBS    v1    v2    v3
    
      1    a      1    12
      2    a      1    13
      3    a      1    14
      4    a      2    12
      5    a      2    13
      6    a      2    14
      7    a      3    12
      8    a      3    13
      9    a      3    14
     10    b      4    12
     11    b      4    13
     12    b      4    14
     13    b      4    15
     14    b      5    12
     15    b      5    13
     16    b      5    14
     17    b      5    15
    반응형

    댓글