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

[데이터 추출] 비등가 FULL 조인(NON-EQUI FULL JOIN)을 통한 데이터 결합 및 데이터 정렬(SORT) - 104

by 기서무나구물 2022. 10. 2.

포스팅 목차

     

    104. List out all the employees name, job, and salary grade and department name for every one in the company except ‘CLERK’. Sort on salary display the highest salary.

     

    * 사무직(‘CLERK’) 직원을 제외한 직원들의 이름, 직무, 부서명, 직원 급여 등급을 높은(내림차순 기준) 급여 기준으로 정렬하여서 출력하시오.


    • Oracle : 비등가조인(NON-EQUI JOIN), Order by
    • 파이썬 Pandas : pd.merge, assign(), query(), sort_values()
    • R 프로그래밍 : base::merge(), subset(), order()
    • R Dplyr Package : dplyr::inner_join(), dplyr::full_join(), dplyr::filter(), dplyr::arrange()
    • R sqldf Package : 비등가조인(NON-EQUI JOIN), Order by
    • Python pandasql Package : 비등가조인(NON-EQUI JOIN), Order by
    • R data.table Package : 비등가조인(NON-EQUI JOIN) 방식 데이터 결합, order()
    • SAS Proc SQL : 비등가조인(NON-EQUI JOIN), Order by
    • SAS Data Step : Merge 구문, IF 조건문, CROSS JOIN (카테시안 곱) 구현, proc sort
    • Python Dfply Package : @pipe & Def 사용자 정의 함수(inner_join_merge), full_join(), arrange()
    • 파이썬 Base 프로그래밍 :

     


    1. Oracle(오라클)

    사무직(‘CLERK’) 직원을 제외한 emp 테이블과 dept 테이블을 결합(merge)하여 부서명을 추가한 후 salgrade 테이블을 비등가 조인(NON-EQUI JOIN)을 수행하여서 해당 급여를 포함하는 범위의 급여 등급을 선택하여 출력한다.

     

    Oracle Programming
    select empno, ename, sal, dname, grade 
    from  emp e, dept d, salgrade s 
    where e.deptno = d.deptno 
      and e.sal between s.losal and s.hisal 
      and e.job <> 'CLERK' 
    order by sal desc;

     


    2. Python Pandas(파이썬)

    emp 테이블을 self Join하여서 관리자 이름을 추가하고, dept 테이블을 결합(merge)하여 부서명을 추가한 후 salgrade 테이블을 비등가 조인(NON-EQUI JOIN)을 수행하여서 해당 급여를 포함하는 범위의 급여 등급을 선택하여 출력한다.

     

    Python Programming
    pd.merge( pd.merge(emp, dept, how='inner', left_on=['deptno'], right_on=['deptno'])[['job','sal',"deptno","ename","dname"]].assign(foo=1),
              salgrade.assign(foo=1), on ='foo').query("losal <= sal <= hisal & job != 'CLERK' ")[["sal","deptno","ename","dname","losal","hisal"]].sort_values(by=['sal'], ascending=False)

     

    Results
    sal deptno ename dname losal hisal
    5000 10 KING ACCOUNTING 3001 9999
    3000 20 SCOTT RESEARCH 2001 3000
    3000 20 FORD RESEARCH 2001 3000
    2975 20 JONES RESEARCH 2001 3000
    2850 30 BLAKE SALES 2001 3000
    2450 10 CLARK ACCOUNTING 2001 3000
    1600 30 ALLEN SALES 1401 2000
    1500 30 TURNER SALES 1401 2000
    1250 30 WARD SALES 1201 1400
    1250 30 MARTIN SALES 1201 1400

     


    • 위 테이블 결합 작업을 개별적으로 분리하여서 처리
    Python Programming
    withmooc_1 = pd.merge(emp, dept, how='inner', left_on=['deptno'], right_on=['deptno'])[['job','sal',"deptno","ename","dname"]]
    withmooc_2 = pd.merge( withmooc_1.assign(foo=1),salgrade.assign(foo=1), on ='foo').query("losal <= sal <= hisal & job != 'CLERK' ")
    withmooc_2[["sal","deptno","ename","dname","losal","hisal"]].sort_values(by=['sal'], ascending=False).head()

     


    Results
    sal deptno ename dname losal hisal
    5000 10 KING ACCOUNTING 3001 9999
    3000 20 SCOTT RESEARCH 2001 3000
    3000 20 FORD RESEARCH 2001 3000
    2975 20 JONES RESEARCH 2001 3000
    2850 30 BLAKE SALES 2001 3000

     


    3. R Programming (R Package)

    emp 테이블을 self Join하여서 관리자 이름을 추가하고, dept 테이블을 결합(merge)하여 부서명을 추가한 후에 salgrade 테이블을 비등가 조인(NON-EQUI JOIN)을 수행하여서 해당 급여를 포함하는 범위의 급여 등급을 선택하여 출력한다. with 구문을 사용하여서 테이블 명 지정하지 않고 변수명을 바로 지정할 수 있다.

     

    R Programming
    %%R
    withmooc <- subset( base::merge( ( base::merge( emp ,
                                                    dept, by.x=c("deptno"),by.y=c("deptno"),all=F )[,c("job","sal","deptno","ename","dname")]
                                      ),
                                      salgrade, by = character(),all.x=TRUE, all.y=TRUE )[,c("job","sal","deptno","ename","dname","losal","hisal")],
                        between(sal, losal, hisal) & job != 'CLERK')
    
    withmooc[order(-withmooc$sal), ]
    
    withmooc[with(withmooc, order(-sal)), ] # with 구문을 사용하여서 테이블 명 지정하지 않고 변수명을 바로 지정 할 수 있다.

     

    Results
             job  sal deptno  ename      dname losal hisal
    58 PRESIDENT 5000     10   KING ACCOUNTING  3001  9999
    49   ANALYST 3000     20   FORD   RESEARCH  2001  3000
    50   ANALYST 3000     20  SCOTT   RESEARCH  2001  3000
    48   MANAGER 2975     20  JONES   RESEARCH  2001  3000
    52   MANAGER 2850     30  BLAKE      SALES  2001  3000
    43   MANAGER 2450     10  CLARK ACCOUNTING  2001  3000
    37  SALESMAN 1600     30  ALLEN      SALES  1401  2000
    41  SALESMAN 1500     30 TURNER      SALES  1401  2000
    25  SALESMAN 1250     30   WARD      SALES  1201  1400
    26  SALESMAN 1250     30 MARTIN      SALES  1201  1400

     


    • 위 테이블 결합 작업을 개별적으로 분리하여서 처리
    R Programming
    %%R
    
    withmooc_1 <- base::merge( emp , dept, by.x=c("deptno"),by.y=c("deptno"),all=F )[,c("job","sal","deptno","ename","dname")]
    withmooc_2 <- base::merge( withmooc_1, salgrade, by = character(),all.x=TRUE, all.y=TRUE )[,c("job","sal","deptno","ename","dname","losal","hisal")]
    withmooc_3 <- subset( withmooc_2, between(sal, losal, hisal) & job != 'CLERK' )
    
    withmooc_3[with(withmooc_3, order(-sal)), ]

     

    Results
             job  sal deptno  ename      dname losal hisal
    58 PRESIDENT 5000     10   KING ACCOUNTING  3001  9999
    49   ANALYST 3000     20   FORD   RESEARCH  2001  3000
    50   ANALYST 3000     20  SCOTT   RESEARCH  2001  3000
    48   MANAGER 2975     20  JONES   RESEARCH  2001  3000
    52   MANAGER 2850     30  BLAKE      SALES  2001  3000
    43   MANAGER 2450     10  CLARK ACCOUNTING  2001  3000
    37  SALESMAN 1600     30  ALLEN      SALES  1401  2000
    41  SALESMAN 1500     30 TURNER      SALES  1401  2000
    25  SALESMAN 1250     30   WARD      SALES  1201  1400
    26  SALESMAN 1250     30 MARTIN      SALES  1201  1400

     


    4. R Dplyr Package

    emp 테이블을 self Join하여서 관리자 이름을 추가하고, dept 테이블을 결합(inner_join)하여 부서명을 추가한 후에 salgrade 테이블을 비등가 조인(NON-EQUI JOIN)을 수행하여서 해당 급여를 포함하는 범위의 급여 등급을 선택하여 출력한다.

     

    R Programming
    %%R
    
    emp %>% 
      dplyr::inner_join( dept    , by = c('deptno' = 'deptno'))   %>%
      dplyr::full_join( salgrade , by = character())              %>%
      dplyr::filter(between(sal, losal, hisal ) & job != 'CLERK') %>%
      dplyr::select(empno,dname,grade,sal )                       %>%
      dplyr::arrange(-sal)

     

    Results
    # A tibble: 10 x 4
       empno dname      grade   sal
       <dbl> <chr>      <dbl> <dbl>
     1  7839 ACCOUNTING     5  5000
     2  7788 RESEARCH       4  3000
     3  7902 RESEARCH       4  3000
     4  7566 RESEARCH       4  2975
     5  7698 SALES          4  2850
     6  7782 ACCOUNTING     4  2450
     7  7499 SALES          3  1600
     8  7844 SALES          3  1500
     9  7521 SALES          2  1250
    10  7654 SALES          2  1250

     


    5. R sqldf Package

    emp 테이블을 self Join하여서 관리자 이름을 추가하고, dept 테이블을 결합(merge)하여 부서명을 추가한 후 salgrade 테이블을 비등가 조인(NON-EQUI JOIN)을 수행하여서 해당 급여를 포함하는 범위의 급여 등급을 선택하여 출력한다.

     

    R Programming
    %%R
    
    sqldf("select empno, ename, sal, dname, grade 
           from  emp e, dept d, salgrade s 
           where e.deptno = d.deptno 
             and e.sal between s.losal and s.hisal 
             and e.job <> 'CLERK' 
           order by sal desc;")

     

    Results
       empno  ename  sal      dname grade
    1   7839   KING 5000 ACCOUNTING     5
    2   7788  SCOTT 3000   RESEARCH     4
    3   7902   FORD 3000   RESEARCH     4
    4   7566  JONES 2975   RESEARCH     4
    5   7698  BLAKE 2850      SALES     4
    6   7782  CLARK 2450 ACCOUNTING     4
    7   7499  ALLEN 1600      SALES     3
    8   7844 TURNER 1500      SALES     3
    9   7521   WARD 1250      SALES     2
    10  7654 MARTIN 1250      SALES     2

     


    6. Python pandasql Package

    사무직(‘CLERK’) 직원을 제외한 emp 테이블과 dept 테이블을 결합(merge)하여 부서명을 추가한 후 salgrade 테이블을 비등가 조인(NON-EQUI JOIN)을 수행하여서 해당 급여를 포함하는 범위의 급여 등급을 선택하여 출력한다.

     

    Python Programming
    ps.sqldf("select e.empno, e.ename, e.sal, d.dname, s.grade  \
              from emp e                                        \
                   inner join dept d                            \
                         ON e.deptno=d.deptno                   \
                   inner join salgrade s                        \
                         ON e.sal between s.losal and s.hisal   \
             where e.job<>'CLERK'                               \
             order by e.sal desc").head()

     


    Results
    empno ename sal dname grade
    7839 KING 5000 ACCOUNTING 5
    7788 SCOTT 3000 RESEARCH 4
    7902 FORD 3000 RESEARCH 4
    7566 JONES 2975 RESEARCH 4
    7698 BLAKE 2850 SALES 4

     


    7. R data.table Package

    • 1차 : emp 테이블을 양쪽에 지정하여서 self Join을 수행하여 관리자 이름을 추가
    • 2차 : dept 테이블을 결합(DT 문법)하여 부서명
    • 3차 : salgrade 테이블을 비등가조인(NON-EQUI JOIN) 방식으로 결합하여 해당 급여를 포함하는 범위의 급여 등급을 선택하여 출력.
    R Programming
    %%R
    
    DT          <- data.table(emp)
    dept_DT     <- data.table(dept)
    salgrade_DT <- data.table(salgrade)
    
    DT[dept_DT, nomatch=NULL, 
                on = .( deptno=deptno ), 
                .(sal,deptno,ename,dname,job)][salgrade_DT, nomatch=NULL,
                                                            on = .( sal >= losal , sal <= hisal),
                                                            .(x.sal,deptno,ename,dname,losal,hisal,job)][ job != 'CLERK' ,][order(- x.sal)]

     

    Results
        x.sal deptno  ename      dname losal hisal       job
     1:  5000     10   KING ACCOUNTING  3001  9999 PRESIDENT
     2:  3000     20  SCOTT   RESEARCH  2001  3000   ANALYST
     3:  3000     20   FORD   RESEARCH  2001  3000   ANALYST
     4:  2975     20  JONES   RESEARCH  2001  3000   MANAGER
     5:  2850     30  BLAKE      SALES  2001  3000   MANAGER
     6:  2450     10  CLARK ACCOUNTING  2001  3000   MANAGER
     7:  1600     30  ALLEN      SALES  1401  2000  SALESMAN
     8:  1500     30 TURNER      SALES  1401  2000  SALESMAN
     9:  1250     30   WARD      SALES  1201  1400  SALESMAN
    10:  1250     30 MARTIN      SALES  1201  1400  SALESMAN

     


    • 위 테이블 결합 작업을 개별적으로 분리하여서 처리
    R Programming
    %%R
    
    DT_1 = DT[dept_DT      , nomatch=NULL, on = .( deptno=deptno )             , .(sal,deptno,ename,dname,job)]
    DT_2 = DT_1[salgrade_DT, nomatch=NULL, on = .( sal >= losal , sal <= hisal), .(x.sal,deptno,ename,dname,losal,hisal,job)]
    
    DT_2[ job != 'CLERK' ,][order(- x.sal)]

     

    Results
        x.sal deptno  ename      dname losal hisal       job
     1:  5000     10   KING ACCOUNTING  3001  9999 PRESIDENT
     2:  3000     20  SCOTT   RESEARCH  2001  3000   ANALYST
     3:  3000     20   FORD   RESEARCH  2001  3000   ANALYST
     4:  2975     20  JONES   RESEARCH  2001  3000   MANAGER
     5:  2850     30  BLAKE      SALES  2001  3000   MANAGER
     6:  2450     10  CLARK ACCOUNTING  2001  3000   MANAGER
     7:  1600     30  ALLEN      SALES  1401  2000  SALESMAN
     8:  1500     30 TURNER      SALES  1401  2000  SALESMAN
     9:  1250     30   WARD      SALES  1201  1400  SALESMAN
    10:  1250     30 MARTIN      SALES  1201  1400  SALESMAN

     


    8. SAS Proc SQL

    사무직(‘CLERK’) 직원을 제외한 emp 테이블과 dept 테이블을 결합(merge)하여 부서명을 추가한 후 salgrade 테이블을 비등가 조인(NON-EQUI JOIN)을 수행하여서 해당 급여를 포함하는 범위의 급여 등급을 선택하여 출력한다.

     

    SAS Programming
    %%SAS sas
    
    PROC SQL;
      CREATE TABLE STATSAS_1 AS
        select empno, ename, sal, dname, grade 
        from  emp e, dept d, salgrade s 
        where e.deptno=d.deptno 
          and e.sal between s.losal and s.hisal 
          and e.job<>'CLERK' 
        order 
           by sal;
    QUIT;
    
    PROC SORT DATA=STATSAS_1;
          BY EMPNO;
    RUN;
    PROC PRINT data=STATSAS_1(obs=3);RUN;

     


    Results
    empno ename sal dname grade
    7499 ALLEN 1600 SALES 3
    7521 WARD 1250 SALES 2
    7566 JONES 2975 RESEARCH 4

     


    9. SAS Data Step

     

    SAS Programming
    %%SAS sas
    
    PROC SORT DATA=emp OUT=EMP_1;
         BY deptno;
    RUN;
    
    proc sort data=dept out=dept_1;
         by deptno;
    run;
    
    DATA STATSAS_3; 
     merge EMP_1(in=a) dept_1(in=b);
         by deptno;
         if a and b;
    RUN;
    
    DATA STATSAS_4; 
     SET STATSAS_3;
         DO I=1 TO KOBS; 
            SET salgrade NOBS=KOBS POINT=I;
            IF  (SAL >= losal AND SAL <= hisal) AND job NE 'CLERK' THEN OUTPUT;
         END;
         KEEP EMPNO ENAME SAL DNAME GRADE;
    RUN;
    PROC SORT DATA=STATSAS_4;
          BY EMPNO;
    RUN;
    PROC PRINT data=STATSAS_4(obs=3);RUN;

     


    Results
    empno ename sal dname grade
    7499 ALLEN 1600 SALES 3
    7521 WARD 1250 SALES 2
    7566 JONES 2975 RESEARCH 4

     


    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( dept , left_on  = ["deptno"], right_on = ["deptno"])    >> \
      full_join( salgrade.assign(foo=1), by='foo' )                             >> \
      filter_by( X.sal.between(X.losal, X.hisal), X.job != 'CLERK')             >> \
      select(X.empno,X.dname,X.ename,X.grade,X.sal )                            >> \
      arrange(~ X.sal)                                                          >> \
      head()

     


    Results
    empno dname ename grade sal
    7839 ACCOUNTING KING 5 5000
    7788 RESEARCH SCOTT 4 3000
    7902 RESEARCH FORD 4 3000
    7566 RESEARCH JONES 4 2975
    7698 SALES BLAKE 4 2850

     


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

    반응형

    댓글