본문 바로가기
통계프로그램 비교 시리즈/프로그래밍비교(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 예제로 만나는 테이블 데이터 전처리 방법 리스트

반응형

댓글