본문 바로가기
통계프로그램 비교 시리즈/프로그래밍비교(Oracle,Python,R,SAS)

[데이터 추출] 비등가 조인에 해당하는 데이터 추출 - 97

by 기서무나구물 2022. 9. 28.

포스팅 목차

     

    97. Display grade and employees name for the dept no 10 or 30 but grade is not 4, while joined the company before 31-dec-82.

     

    * 부서번호 10 또는 30 에 근무하고, 급여 등급이 4 등급 이외 등급이고, 1982년 12월 31일 이전에 입사한 직원의 정보를 출력하시오.


    • Oracle : 비등가 조인
    • 파이썬 Pandas : pd.merge(), assign(), query()
    • R 프로그래밍 : subset(), Merge(), character(), Between()
    • R Dplyr Package : dplyr::full_join(), dplyr::left_join(), character(), dplyr::filter(), between()
    • R sqldf Package : 비등가 조인
    • Python pandasql Package : 비등가 조인
    • R data.table Package : DT syntax 방식 비등가 조인
    • SAS Proc SQL : 비등가 조인
    • SAS Data Step : CROSS JOIN (카테시안 곱) 구현, IF 조건문
    • Python Dfply Package : left_join(), @pipe & def (inner_join_merge) 사용자 정의 함수, filter_by(), between()
    • 파이썬 Base 프로그래밍 :

     


    1. Oracle(오라클)

    조건절에 위에 명시한 조건을 지정하여서 해당 직원의 정보를 출력한다. salgrade 테이블은 비등가조인으로 해당 급여를 포함하는 범위의 급여 등급을 선택한다.

     

    Oracle Programming
    select ename,grade 
    from   emp,salgrade 
    where  sal between losal and hisal 
      and  deptno in (10,30) 
      and  grade  <> 4 
      and  hiredate <  '31-DEC-82';

     


    2. Python Pandas(파이썬)

    emp 테이블과 salgrade 테이블에 임시 변수(‘foo’)를 지정하여서 임시 변수를 기준으로 cross join(Cartesian Product)을 수행한 후 query 구문에서 왼쪽 테이블의 기준 값을 기준으로 오른쪽 테이블에서 local <= sal <= hisal 사이에 포함된 값(‘grade’)을 선택하고, 이 값을 포함한 추가 조건을 만족하는 직원의 정보를 출력한다.

     

    Python Programming
    pd.merge(emp.assign(foo=1), salgrade.assign(foo=1), on ='foo').query('losal <= sal <= hisal & deptno == [10,30] & grade != 4 & hiredate<"1982/12/31"').drop(['job','comm','deptno'],axis=1)

     

     


    Results
    empno ename mgr hiredate sal foo grade sal hisal
    7499 ALLEN 7698.0 1981/02/20 1600 1 3 1401 2000
    7521 WARD 7698.0 1981/02/22 1250 1 2 1201 1400
    7654 MARTIN 7698.0 1981/09/28 1250 1 2 1201 1400
    7839 KING NaN 1981/11/17 5000 1 5 3001 9999
    7844 TURNER 7698.0 1981/09/08 1500 1 3 1401 2000
    7900 JAMES 7698.0 1981/12/03 950 1 1 700 1200
    7934 MILLER 7782.0 1982/01/23 1300 1 2 1201 1400

     


    3. R Programming (R Package)

    emp 테이블과 salgrade 테이블을 기준 변수에 character()을 지정하여서 cross join(Cartesian Product)을 수행한 후 subset 구문에서 왼쪽 테이블의 기준 값을 기준으로 오른쪽 테이블에서 between(sal, losal, hisal) 사이에 포함된 값(‘grade’)을 선택하고 하고, 이 값을 포함한 추가 조건을 만족하는 직원의 정보를 출력한다.

     

    R Programming
    %%R
    
    subset( merge(emp, salgrade,by= character(),all.x=TRUE, all.y=TRUE),
            between(sal, losal, hisal) & deptno %in% c(10,30) & grade != 4 & hiredate<'1982-12-31' )

     

     

    Results
       empno  ename       job  mgr   hiredate  sal comm deptno fake.x grade losal hisal fake.y
    12  7900  JAMES     CLERK 7698 1981-12-03  950   NA     30      1     1   700  1200      1
    17  7521   WARD  SALESMAN 7698 1981-02-22 1250  500     30      1     2  1201  1400      1
    19  7654 MARTIN  SALESMAN 7698 1981-09-28 1250 1400     30      1     2  1201  1400      1
    28  7934 MILLER     CLERK 7782 1982-01-23 1300   NA     10      1     2  1201  1400      1
    30  7499  ALLEN  SALESMAN 7698 1981-02-20 1600  300     30      1     3  1401  2000      1
    38  7844 TURNER  SALESMAN 7698 1981-09-08 1500    0     30      1     3  1401  2000      1
    65  7839   KING PRESIDENT   NA 1981-11-17 5000   NA     10      1     5  3001  9999      1

     


    4. R Dplyr Package

    emp 테이블과 salgrade 테이블을 기준 변수에 character()을 지정하여서 full_join 문법을 사용하여서 cross join(Cartesian Product)을 수행한 후 filter 함수에서 왼쪽 테이블의 기준 값을 기준으로 오른쪽 테이블에서 between(sal, losal, hisal) 사이에 포함된 값(‘grade’)을 선택하고 하고, 이 값을 포함한 추가 조건을 만족하는 직원의 정보를 출력한다.

     

    R Programming
    %%R
    
    emp %>% 
      dplyr::full_join(salgrade, by = character()) %>%
      dplyr::filter( between(sal, losal, hisal ) & deptno %in% c(10,30) & grade != 4 & hiredate<'1982-12-31' )

     

     

    Results
    # A tibble: 7 x 13
      empno ename  job         mgr hiredate     sal  comm deptno fake.x grade losal hisal fake.y
      <dbl> <chr>  <chr>     <dbl> <date>     <dbl> <dbl>  <dbl>  <dbl> <dbl> <dbl> <dbl>  <dbl>
    1  7499 ALLEN  SALESMAN   7698 1981-02-20  1600   300     30      1     3  1401  2000      1
    2  7521 WARD   SALESMAN   7698 1981-02-22  1250   500     30      1     2  1201  1400      1
    3  7654 MARTIN SALESMAN   7698 1981-09-28  1250  1400     30      1     2  1201  1400      1
    4  7839 KING   PRESIDENT    NA 1981-11-17  5000    NA     10      1     5  3001  9999      1
    5  7844 TURNER SALESMAN   7698 1981-09-08  1500     0     30      1     3  1401  2000      1
    6  7900 JAMES  CLERK      7698 1981-12-03   950    NA     30      1     1   700  1200      1
    7  7934 MILLER CLERK      7782 1982-01-23  1300    NA     10      1     2  1201  1400      1

     


    • Cross Join 생성 예제(dummy= 사용 방식)

    emp 테이블과 salgrade 테이블에 임시 dummy 변수를 지정하고, left_join 문법을 사용하여서 임시 변수를 기준으로 cross join(Cartesian Product)을 수행하여서 해당 급여가 포함하는 범위의 급여 등급을 선택한다.

    R Programming
    %%R
    
    emp %>%
      dplyr::mutate(dummy=TRUE) %>%
      dplyr::left_join ( salgrade %>%mutate(dummy=TRUE) ) %>%
      head()

     

     

    Results
    Joining, by = c("fake", "dummy")
    # A tibble: 6 x 13
      empno ename job        mgr hiredate     sal  comm deptno  fake dummy grade losal hisal
      <dbl> <chr> <chr>    <dbl> <date>     <dbl> <dbl>  <dbl> <dbl> <lgl> <dbl> <dbl> <dbl>
    1  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1 TRUE      1   700  1200
    2  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1 TRUE      2  1201  1400
    3  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1 TRUE      3  1401  2000
    4  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1 TRUE      4  2001  3000
    5  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1 TRUE      5  3001  9999
    6  7499 ALLEN SALESMAN  7698 1981-02-20  1600   300     30     1 TRUE      1   700  1200

     


    • Cross Join 생성 예제(가변수 생성 방식)

    emp 테이블과 salgrade 테이블에 임시 fake 변수를 지정하고, full_join 문법을 사용하여서 임시 변수(‘fake’)를 기준으로 cross join(Cartesian Product)을 수행하여서 해당 급여가 포함하는 범위의 급여 등급을 선택한다.

    R Programming
    %%R
    
    emp$fake      <- 1
    salgrade$fake <- 1
    
    full_join(emp, salgrade, by = "fake") %>%
      head()

     

     

    Results
    # A tibble: 6 x 12
      empno ename job        mgr hiredate     sal  comm deptno  fake grade losal hisal
      <dbl> <chr> <chr>    <dbl> <date>     <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>
    1  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1     1   700  1200
    2  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1     2  1201  1400
    3  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1     3  1401  2000
    4  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1     4  2001  3000
    5  7369 SMITH CLERK     7902 1980-12-17   800    NA     20     1     5  3001  9999
    6  7499 ALLEN SALESMAN  7698 1981-02-20  1600   300     30     1     1   700  1200

     


    5. R sqldf Package

    조건절에 위에서 명시한 조건을 지정하여서 해당 직원의 정보를 출력한다. salgrade 테이블은 비등가조인(NON-EQUI JOIN) 으로 해당 급여를 포함하는 범위의 급여 등급을 선택한다.

     

    R Programming
    %%R
    
    sqldf("select ename,grade 
           from   emp,salgrade 
           where  sal between losal and hisal 
             and  deptno in (10,30) 
             and  grade <> 4 
             and  hiredate < '31-DEC-82';")

     

     

    Results
       ename grade
    1  ALLEN     3
    2   WARD     2
    3 MARTIN     2
    4   KING     5
    5 TURNER     3
    6  JAMES     1
    7 MILLER     2

     


    6. Python pandasql Package

    조건절에 위에 명시한 조건을 지정하여서 해당 직원의 정보를 출력한다. salgrade 테이블은 비등가조인으로 해당 급여를 포함하는 범위의 급여 등급을 선택한다.

    Python Programming
    ps.sqldf("select ename,grade                 \
              from   emp,salgrade                \
              where  sal between losal and hisal \
                and  deptno in (10,30)           \
                and  grade <> 4                  \
                and  hiredate<'31-DEC-82';")

     

     


    Results
    ename grade
    ALLEN 3
    WARD 2
    MARTIN 2
    KING 5
    TURNER 3
    JAMES 1
    MILLER 2

     


    7. R data.table Package

    emp 테이블과 salgrade 테이블을 기준으로 비등가조인(NON-EQUI JOIN) 으로 해당 급여를 포함하는 범위의 급여 등급을 선택하고, 이 값을 포함한 추가 조건을 만족하는 직원의 정보를 출력한다.

    • data.table은 비등가조인(NON-EQUI JOIN)을 지원하는 것이 장점이다.

     

    R Programming
    %%R
    
    DT          <- data.table(emp)
    dept_DT     <- data.table(dept)
    salgrade_DT <- data.table(salgrade)
    
    DT[salgrade_DT, nomatch=NULL, on = .( sal >= losal , sal <= hisal), ][deptno %in% c(10,30) & grade!=4 & hiredate<'1982-12-31' ,empno:deptno]

     

     

    Results
       empno  ename       job  mgr   hiredate  sal comm deptno
    1:  7900  JAMES     CLERK 7698 1981-12-03  700   NA     30
    2:  7521   WARD  SALESMAN 7698 1981-02-22 1201  500     30
    3:  7654 MARTIN  SALESMAN 7698 1981-09-28 1201 1400     30
    4:  7934 MILLER     CLERK 7782 1982-01-23 1201   NA     10
    5:  7499  ALLEN  SALESMAN 7698 1981-02-20 1401  300     30
    6:  7844 TURNER  SALESMAN 7698 1981-09-08 1401    0     30
    7:  7839   KING PRESIDENT   NA 1981-11-17 3001   NA     10

     


    8. SAS Proc SQL

    조건절에 위에 명시한 조건을 지정하여서 해당 직원의 정보를 출력한다. salgrade 테이블은 비등가조인으로 해당 급여를 포함하는 범위의 급여 등급을 선택한다.

    SAS Programming
    %%SAS sas
    
    PROC SQL;
      CREATE TABLE STATSAS_1 AS
        select ename,grade 
        from   emp,salgrade 
        where  sal between losal and hisal 
          and  deptno in(10,30) 
          and  grade    NE 4 
          and  hiredate <  '31dec82'd;
    QUIT;
    PROC PRINT;RUN;

     

     


    Results
    ename grade
    ALLEN 3
    WARD 2
    MARTIN 2
    KING 5
    TURNER 3
    JAMES 1
    MILLER 2

     


     

    SAS Programming
    %%SAS sas
    
    PROC SQL;
      CREATE TABLE STATSAS_2 AS
        select ename,grade 
        from   emp , salgrade 
        where  sal between losal and hisal 
          and  deptno   in (10,30) 
          and  grade    NE 4 
          and  hiredate <  mdy(12,31,1982);
    QUIT;
    PROC PRINT;RUN;

     

     


    Results
    ename grade
    ALLEN 3
    WARD 2
    MARTIN 2
    KING 5
    TURNER 3
    JAMES 1
    MILLER 2

     


    9. SAS Data Step

    • DATA STEP(CROSS JOIN-카테시안 곱)
    SAS Programming
    %%SAS sas
    
    DATA STATSAS_3; 
     SET EMP;
         DO I=1 TO KOBS; 
            SET salgrade NOBS=KOBS POINT=I;
            IF  SAL >= losal AND SAL <= hisal
            and deptno   in (10,30) 
            and grade    NE 4 
            and hiredate <  mdy(12,31,1982) THEN OUTPUT;
         END;    
    RUN;
    
    PROC PRINT;RUN;

     


    10. Python Dfply Package

     

    Python Programming
    @pipe
    def inner_join_merge(df, other, left_on,right_on,suffixes=['_x','_y']):
    
        joined = df.merge(other, how='inner', left_on=left_on,
                          right_on=right_on , suffixes=suffixes)
        return joined
    
    emp.assign(foo=1) >> \
      inner_join_merge( salgrade.assign(foo=1), left_on  = ["foo"], right_on = ["foo"] )  >> \
      filter_by(X.sal.between(X.losal, X.hisal, inclusive = True)  , \
                X.deptno.isin([10,30]), \
                X.grade != 4, \
                X.hiredate < "1982/12/31")                                                >> \
      select(~X.job, ~X.hiredate, ~X.comm)

     

     


    Results
    empno ename mgr sal deptno foo grade losal hisal
    7499 ALLEN 7698.0 1600 30 1 3 1401 2000
    7521 WARD 7698.0 1250 30 1 2 1201 1400
    7654 MARTIN 7698.0 1250 30 1 2 1201 1400
    7839 KING NaN 5000 10 1 5 3001 9999
    7844 TURNER 7698.0 1500 30 1 3 1401 2000
    7900 JAMES 7698.0 950 30 1 1 700 1200
    7934 MILLER 7782.0 1300 10 1 2 1201 1400

     


    Python Programming
    emp                                                                                  >> \
      mutate(dummy=1)                                                                    >> \
      left_join( salgrade >> mutate(dummy=1) )                                           >> \
      filter_by(X.sal.between(X.losal, X.hisal, inclusive = True)  , \
                X.deptno.isin([10,30]),                              \
                X.grade != 4,                                        \
                X.hiredate < "1982/12/31")                                               >> \
      select(~X.job, ~X.hiredate, ~X.comm)

     

     

    Results
    empno ename mgr sal deptno dummy grade losal hisal
    7499 ALLEN 7698.0 1600 30 1 3 1401 2000
    7521 WARD 7698.0 1250 30 1 2 1201 1400
    7654 MARTIN 7698.0 1250 30 1 2 1201 1400
    7839 KING NaN 5000 10 1 5 3001 9999
    7844 TURNER 7698.0 1500 30 1 3 1401 2000
    7900 JAMES 7698.0 950 30 1 1 700 1200
    7934 MILLER 7782.0 1300 10 1 2 1201 1400

     



    [SQL, Pandas, R Prog, Dplyr, SQLDF, PANDASQL, DATA.TABLE]   SQL EMP 예제로 만나는 테이블 데이터 처리 방법 리스트

    반응형

    댓글