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

[비등가 데이터 결합] 특정 조건을 만족하는 데이터 추출 - 상관 서브쿼리(Any) - 149 (오라클 SQL, R, Python, SAS)

by 기서무나구물 2023. 1. 3.

포스팅 목차

    149. Display those mangers who are getting less than his employees Sal.

     

    * 담당하고 있는 부서의 부서원들 보다 적은 급여를 수령하는 관리자의 정보를 출력하시오.


    • 파이썬 & R 패키지 호출 및 예제 데이터 생성 링크
    • Any : 61/62/113/114
    • 상관서브쿼리 참고 : 112
    • [데이터 추출] 특정 조건을 만족하는 데이터 추출 - 상관 서브쿼리(Any), 비등가 데이터 결합
    • 데이터 전처리 - SQL, Pandas, R Prog, Dplyr, Dfply, SQLDF, PANDASQL, DATA.TABLE, SAS, Proc Sql
    • Oracle : 상관 서브쿼리, Any 연산자, Min(), 비등가 조인
    • 파이썬 Pandas : pd.merge(), .astype(np.float64), Query(), info()
    • R 프로그래밍 : subset(), Merge(), aggregate() 의 사용자 정의 함수, Min()
    • R Dplyr Package : dplyr::inner_join(), summarise()의 최소값(Min)
    • R sqldf Package : 상관 서브쿼리, Any 연산자, Min(), 비등가 조인
    • Python pandasql Package : 상관 서브쿼리, Any 연산자, Min(), 비등가 조인
    • R data.table Package : Merge 방식 데이터 결합, Min(), %in%, DT[]
    • SAS Proc SQL : 상관 서브쿼리, Any 연산자, Min(), 비등가 조인
    • SAS Data Step : proc summary 의 Min, Merge 구문, IF 조건문, Rename 구문
    • Python Dfply Package : @pipe & def 사용자 정의 함수(inner_join_merge), summarize(), Min(), Filter_by()
    • 파이썬 Base 프로그래밍 :

     


    1. Oracle(오라클)

    상관 서브쿼리를 사용하여 서브쿼리 내에서 본인이 관리자로 담당하고 있는 부서의 부서원 급여와 메인(외부)쿼리에 위치한 본인의 급여를 비교하여서 본인의 급여가 담당부서 직원의 급여보다 적은 경우가 존재하면(직원 한 사람 이상이 본인 급여 보다 더 많이 수령하는 경우) 급여를 수령하는 관리자의 직원 정보를 출력하시오. ANY 연산자를 사용하여서 서브쿼리에서 반환되는 값과 비교하여서 하나 이상을 만족하는 경우에 해당 결과를 반환한다.

     

    Oracle Programming
    Select empno 
    from   emp e 
    where  sal < any(select sal from emp where mgr = e.empno);

     


    인라인뷰(Inline view)에서 관리자 사원번호를 기준으로 소속된 직원들의 최소 급여를 집계 후 emp 테이블과 self join 형식으로 결합하여서 본인이 관리자(‘mgr’)로 담당하고 있는 부서의 부서원들의 최소 급여(‘b.min_sal’)보다 적은 급여(a.sal)를 수령하고 있는 관리자의 직원 정보(‘a.*’)를 출력한다.

     

    Oracle Programming
    select a.deptno,a.sal,a.empno,a.ename
    from   emp a, (select mgr,min(sal) min_sal from emp group by mgr) b 
    where  a.empno = b.mgr 
      and  a.sal   < b.min_sal

     


    2. Python Pandas(파이썬)

    emp 테이블의 사원번호(‘empno’)가 관리자 사원번호(‘mgr’)에 존재하는 데이터를 추출하고, 관리자 사원번호를 기준으로 속해있는 사원들의 급여(‘sal’) 중에서 최소 급여를 추출하여 float64로 형 변환한다. 이 2개의 결과를 merge() 함수로 사원번호와 관리자 사원번호를 기준으로 내부조인(inner Join)을 수행하여 관리자의 급여(‘sal’)가 관리하고 있는 부서원의 최소 급여(‘amin’)보다 적게 수령하는 관리자의 사원 정보(왼쪽 emp 테이블)를 출력한다.

     

    • emp 테이블의 급여(‘sal’)가 float64 형식으로 저장되어 있어서 최소 급여에 대하여 float64로 변환을 해야 Join 이 실행 됨.

     

    Python Programming
    pd.merge(emp[(emp.empno.isin(emp.mgr))], 
             (emp['sal'].groupby(emp['mgr']).agg([np.min]).reset_index().astype(np.float64)), 
             how='inner', 
             left_on=['empno'], right_on=['mgr']).query('sal < amin')

     

    Results
      empno ename job mgr_x hiredate sal comm deptno mgr_y amin
    0 7566 JONES MANAGER 7839.0 1981/04/02 2975 NaN 20 7566.0 3000.0

     


    • [참고] emp 테이블의 속성 정보
    Python Programming
    emp.info()

     

    Results
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 14 entries, 0 to 13
    Data columns (total 8 columns):
     #   Column    Non-Null Count  Dtype  
    ---  ------    --------------  -----  
     0   empno     14 non-null     int64  
     1   ename     14 non-null     object 
     2   job       14 non-null     object 
     3   mgr       13 non-null     float64
     4   hiredate  14 non-null     object 
     5   sal       14 non-null     int64  
     6   comm      4 non-null      float64
     7   deptno    14 non-null     int64  
    dtypes: float64(2), int64(3), object(3)
    memory usage: 1.0+ KB

     


    3. R Programming (R Package)

    관리자 사원번호를 기준으로 관리하고 있는 사원들의 급여(‘sal’) 중에서 최소 급여를 추출한다. emp 테이블과 앞에서 추출한 결과를 merge() 함수로 사원번호와 관리자 사원번호를 기준으로 내부조인(inner Join)을 수행하여 관리자의 급여(‘sal.x’)가 관리하고 있는 부서원의 최소 급여(‘sal.y’)보다 적게 수령하는 관리자의 사원 정보(왼쪽 emp 테이블)를 출력한다.

     

    R Programming
    %%R
    
    subset( merge( emp,
                   ( aggregate(sal ~ mgr, data = emp, FUN = function(x) c(sal_min = min(x) )) ),
                   by.x=c("empno"),
                   by.y=c("mgr"),all=F) ,
            (sal.x < sal.y) )

     

    Results
      empno ename     job  mgr   hiredate sal.x comm deptno sal.y
    1  7566 JONES MANAGER 7839 1981-04-02  2975   NA     20  3000

     


    4. R Dplyr Package

    inner_join() 함수 내부에서 관리자 사원번호를 기준으로 관리하고 있는 사원들의 급여(‘sal’) 중에서 최소 급여(‘sal_min’)를 집계한다. emp 테이블과 앞에서 추출한 결과를 dplyr::inner_join() 함수로 사원번호와 관리자 사원번호를 기준으로 내부조인(inner Join)을 수행하여 관리자의 급여(‘sal’)가 관리하고 있는 부서원의 최소 급여(‘sal_min’)보다 적게 수령하는 관리자의 사원 정보(왼쪽 emp 테이블 정보)를 출력한다.

     

    R Programming
    %%R
    
    emp %>% 
      dplyr::inner_join (emp %>% group_by(mgr) %>% summarise(sal_min = min(sal, na.rm=TRUE)) , by = c("empno" = "mgr") ) %>%
      dplyr::filter(sal < sal_min)

     

    Results
    `summarise()` ungrouping output (override with `.groups` argument)
    # A tibble: 1 x 9
      empno ename job       mgr hiredate     sal  comm deptno sal_min
      <dbl> <chr> <chr>   <dbl> <date>     <dbl> <dbl>  <dbl>   <dbl>
    1  7566 JONES MANAGER  7839 1981-04-02  2975    NA     20    3000

     


    5. R sqldf Package

    • SQLite에서는 ANY 구문을 지원하지 않음.
    • ANY : sal > ANY(SELECT sal FROM emp WHERE job=’SALESMAN’)
    • min : sal > (SELECT min(sal) FROM emp WHERE job=’SALESMAN’)
    • ALL : sal > ALL(SELECT sal FROM emp WHERE job=’SALESMAN’)
    • max : sal > (SELECT max(sal) FROM emp WHERE job=’SALESMAN’)

    상관 서브쿼리를 사용하여 서브쿼리 내에서 본인이 관리자로 담당하고 있는 부서의 부서원 최소급여와 메인(외부)쿼리에 위치한 본인의 급여를 비교하여서 본인의 급여가 담당부서 직원의 최소급여보다 적게 수령하는 관리자의 직원 정보를 출력한다. 서브쿼리에서 반환되는 최소 급여와 비교하여서 관리자의 급여가 적은 경우 해당 결과를 반환한다.

     

    R Programming
    %%R
    
    sqldf("select ename,sal,deptno 
           from   emp e 
           where  sal < (select min(sal) from emp where mgr=e.empno)")

     

    Results
      ename  sal deptno
    1 JONES 2975     20

     


    인라인뷰(Inline view)에서 관리자 사원번호를 기준으로 소속된 직원들의 최소 급여를 집계 후 emp 테이블과 self join 형식으로 결합하여서 본인이 관리자(‘mgr’)로 담당하고 있는 부서의 부서원들의 최소 급여(‘b.min_sal’)보다 적은 급여(a.sal)를 수령하고 있는 관리자의 직원 정보(‘a.*’)를 출력한다.

     

    R Programming
    %%R
    
    sqldf(" select a.deptno,a.sal,a.empno,a.ename
            from   emp a, ( select mgr,min(sal) min_sal from emp group by mgr) b 
            where  a.empno = b.mgr 
              and  a.sal   < b.min_sal")

     

    Results
      deptno  sal empno ename
    1     20 2975  7566 JONES

     


    6. Python pandasql Package

     

    Python Programming
    ps.sqldf(" select distinct a.sal,a.empno,a.ename,b.sal   \
               from   emp a, emp b                           \
               where  a.empno =b.mgr and a.sal<b.sal")

     

    Results
      sal empno ename sal
    0 2975 7566 JONES 3000

     


    7. R data.table Package

    emp 테이블의 사원번호(‘empno’)가 관리자 사원번호(‘mgr’)에 존재하는 데이터를 추출하고, 관리자 사원번호를 기준으로 관리하고 있는 사원들의 급여(‘sal’) 중에서 최소 급여(‘sal_min’)를 추출한다. 이 2개의 결과를 merge() 함수로 사원번호(‘empno’)와 관리자 사원번호(‘mgr’)를 기준으로 내부조인(inner Join)을 수행하여 관리자의 급여(‘sal’)가 관리하고 있는 부서원의 최소 급여(‘sal_min’)보다 적게 수령하는 관리자의 사원 정보(왼쪽 emp 테이블)를 출력한다.

     

    R Programming
    %%R
    DT          <- data.table(emp)
    
    merge( DT[ DT[,(empno %in% DT[]$mgr)  ] ], 
           DT[ , .(sal_min = min(sal)), by = .(mgr)],
           by.x=c("empno"),
           by.y=c("mgr"),all=F)[sal < sal_min]

     

    Results
       empno ename     job  mgr   hiredate  sal comm deptno sal_min
    1:  7566 JONES MANAGER 7839 1981-04-02 2975   NA     20    3000

     


    8. SAS Proc SQL

    상관 서브쿼리를 사용하여 서브쿼리 내에서 본인이 관리자로 담당하고 있는 부서의 부서원 급여와 메인(외부)쿼리에 위치한 본인의 급여를 비교하여서 본인의 급여가 담당부서 직원의 급여보다 적은 경우가 존재하면(직원 한 사람 이상이 본인 급여 보다 더 많이 수령하는 경우) 급여를 수령하는 관리자의 직원 정보를 출력하시오. ANY 연산자를 사용하여서 서브쿼리에서 반환되는 값과 비교하여서 하나 이상을 만족하는 경우에 해당 결과를 반환한다.

     

    SAS Programming
    %%SAS sas
    
    PROC SQL;
      CREATE TABLE STATSAS_1 AS
        Select empno, sal, deptno
        from   emp e 
        where  sal < any(select sal from emp where mgr = e.empno);
    QUIT;
    PROC PRINT;RUN;

     

    Results
    OBS empno sal deptno
    1 7566 2975 20

     


     

    SAS Programming
    %%SAS sas
    
    PROC SQL;
      CREATE TABLE STATSAS_2 AS
        select ename,sal,deptno 
        from   emp e 
        where  sal < (select min(sal) from emp where mgr=e.empno);
    QUIT;
    PROC PRINT;RUN;

     

    Results
    OBS empno sal deptno
    1 JONES 2975 20

     


    인라인뷰(Inline view)에서 관리자 사원번호를 기준으로 소속된 직원들의 최소 급여를 집계 후 emp 테이블과 self join 형식으로 결합하여서 본인이 관리자(‘mgr’)로 담당하고 있는 부서의 부서원들의 최소 급여(‘b.min_sal’)보다 적은 급여(a.sal)를 수령하고 있는 관리자의 직원 정보(‘a.*’)를 출력한다.

     

    SAS Programming
    %%SAS sas
    
    PROC SQL;
      CREATE TABLE STATSAS_3 AS
        select a.deptno,a.sal,a.empno,a.ename
        from   emp a, ( select mgr,min(sal) as min_sal from emp group by mgr) b 
        where  a.empno = b.mgr 
          and  a.sal   < b.min_sal;
    QUIT;
    PROC PRINT;RUN;

     

    Results
    OBS deptno sal empno ename
    1 20 2975 7566 JONES

     


    9. SAS Data Step

     

    SAS Programming
    %%SAS sas
    
    proc sort data=emp out=emp_1(rename=empno=join_key);
         by empno;
    run;
    
    proc summary data=emp nway;
         class mgr;
         var   sal;
         output out=sal_min(drop=_:) min=sal_min;
    quit;
    
    proc sort data=sal_min out=sal_min_1(rename=mgr=join_key keep=mgr sal_min);
         by mgr;
    run;
    
    DATA STATSAS_4;
     merge emp_1(in=a) sal_min_1(in=b);
         by join_key;
         if a and b;
         if sal < sal_min then output;
         rename join_key = empno;
         keep sal join_key ename sal_min;
    RUN;
    PROC PRINT;RUN;

     

    Results
    OBS empno ename sal sal_min
    1 7566 JONES 2975 3000

     


    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 >> \
      inner_join_merge( (emp >> group_by('mgr') >> summarize ( sal_min = X.sal.min())),
                        left_on = ['empno'] , right_on = ['mgr']) >>\
      filter_by(X.sal < X.sal_min)

     

    Results
      empno ename job mgr_x hiredate sal comm deptno mgr_y sal_min
    0 7566 JONES MANAGER 7839.0 1981/04/02 2975 NaN 20 7566.0 3000

     

     



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

    반응형

    댓글