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

[데이터 추출] 특정 조건을 만족하는 데이터 추출 - 상관 서브쿼리, 평균 - 112

by 기서무나구물 2022. 12. 7.

포스팅 목차

     

    112. Display those managers name whose salary is more than an average salary of his employees.

     

    * 담당하고 있는 부서에 속한 직원들의 평균 급여보다 더 많은 급여를 수령하고 있는 관리자 정보를 출력하시오.


    • 파이썬 & R 패키지 호출 및 예제 데이터 생성 링크
    • 56번 참조(상관서브쿼리 - Correlated Subquery), 61/62번(Any / All)
    • 특정 조건을 만족하는 데이터 추출 - 상관 서브쿼리, 평균
    • 데이터 전처리 - SQL, Pandas, R Prog, Dplyr, Dfply, SQLDF, PANDASQL, DATA.TABLE, SAS, Proc Sql
    • Oracle : 상관 서브쿼리, avg()
    • 파이썬 Pandas : pd.merge(), agg(), np.mean
    • R 프로그래밍 : merge(), subset(), aggregate(), function(x) 사용자 정의 함수, mean()
    • R Dplyr Package : dplyr::inner_join(), summarise(), mean()
    • R sqldf Package : 상관 서브쿼리, avg()
    • Python pandasql Package : 상관 서브쿼리, avg()
    • R data.table Package : DT syntax 방식 데이터 결합, %in%, mean()
    • SAS Proc SQL : 비상관 서브쿼리, avg()
    • SAS Data Step : PROC SORT의 Nodupkey 옵션, Merge 구문, IF 조건문, PROC SUMMARY 의 Mean
    • Python Dfply Package : @pipe & def 사용자 정의 함수(pull_list), @pipe & def 사용자 정의 함수(inner_join_merge), summarize(), mean()
    • 파이썬 Base 프로그래밍 :

     


    1. Oracle(오라클)

    서브쿼리를 사용하여 관리자(‘mgr’) 사원번호 목록에 존재하는 사원번호(‘empno’)를 선택하여서 관리자 역할을 수행하는 직원을 선택하고, 상관서브쿼리를 사용하여서 관리자 본인이 관리하고 있는 부서 직원 평균 급여보다 더 많은 급여를 수령하는 관리자 정보를 출력한다.

     

    Oracle Programming
    select ename, sal 
    from   emp e 
    where  empno in (select mgr from emp) 
      and  e.sal > (select avg(sal) from emp where mgr=e.empno);

     


    2. Python Pandas(파이썬)

    emp 테이블에서 사원번호가 관리자(‘mgr’) 사원번호에 존재하는 관리자들의 데이터를 선택하고, 관리자별 급여 평균을 계산한 후 2개의 추출 결과를 inner Join으로 결합하여 관리자의 급여가 담당하고 있는 부서 직원들의 평균 급여보다 더 많이 수령하는 관리자들을 추출한다.

     

    Python Programming
    pd.merge( emp[(emp.empno.isin(emp.mgr))], 
              (emp['sal'].groupby(emp['mgr']).agg([np.mean])), 
              how='inner', 
              left_on=['empno'], right_on=['mgr']  ).query('sal > mean')

     


    Results
      empno ename job mgr hiredate sal comm deptno mean
    1 7698 BLAKE MANAGER 7839.0 1981/03/01 2850 NaN 30 1310.000000
    2 7782 CLARK MANAGER 7839.0 1981/01/09 2450 NaN 10 1300.000000
    3 7788 SCOTT ANALYST 7566.0 1982/12/09 3000 NaN 20 1100.000000
    4 7839 KING PRESIDENT NaN 1981/11/17 5000 NaN 10 2758.333333
    5 7902 FORD ANALYST 7566.0 1981/12/03 3000 NaN 20 800.000000

     


    3. R Programming (R Package)

    emp 테이블에서 사원번호(‘empno’)가 관리자(‘mgr’) 사원번호에 존재하는 관리자들의 데이터를 선택하고, 관리자별 급여 평균을 계산한 후 2개의 추출 결과를 inner Join으로 결합하여 관리자의 급여가 담당하고 있는 부서 직원들의 평균 급여보다 더 많이 수령하는 관리자들을 추출한다.

     

    R Programming
    %%R
    
    subset( merge( (emp[emp$empno %in% emp$mgr, ]),
                   ( aggregate(sal ~ mgr, data = emp, FUN = function(x) c(sal_mean = mean(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
    2  7698 BLAKE   MANAGER 7839 1981-03-01  2850   NA     30 1310.000
    3  7782 CLARK   MANAGER 7839 1981-01-09  2450   NA     10 1300.000
    4  7788 SCOTT   ANALYST 7566 1982-12-09  3000   NA     20 1100.000
    5  7839  KING PRESIDENT   NA 1981-11-17  5000   NA     10 2758.333
    6  7902  FORD   ANALYST 7566 1981-12-03  3000   NA     20  800.000

     


    4. R Dplyr Package

    emp 테이블에서 사원번호(‘empno’)가 관리자(‘mgr’) 사원번호에 존재하는 관리자들의 데이터를 선택하고, 관리자별 급여 평균을 계산한 후 2개의 추출 결과를 inner Join으로 결합하여 관리자의 급여가 담당하고 있는 부서 직원들의 평균 급여보다 더 많이 수령하는 관리자들을 추출한다.

     

    R Programming
    %%R
    
    emp %>% 
      dplyr::filter(empno %in% ( emp%>%
                                   dplyr::select(mgr) %>%
                                   dplyr::pull()  ) ) %>% 
      dplyr::inner_join (emp %>% group_by(mgr) %>% summarise(sal_mean = mean(sal)) , by = c("empno" = "mgr") ) %>%
      dplyr::filter(sal > sal_mean)

     

    Results
    `summarise()` ungrouping output (override with `.groups` argument)
    # A tibble: 5 x 9
      empno ename job         mgr hiredate     sal  comm deptno sal_mean
      <dbl> <chr> <chr>     <dbl> <date>     <dbl> <dbl>  <dbl>    <dbl>
    1  7698 BLAKE MANAGER    7839 1981-03-01  2850    NA     30    1310 
    2  7782 CLARK MANAGER    7839 1981-01-09  2450    NA     10    1300 
    3  7788 SCOTT ANALYST    7566 1982-12-09  3000    NA     20    1100 
    4  7839 KING  PRESIDENT    NA 1981-11-17  5000    NA     10    2758.
    5  7902 FORD  ANALYST    7566 1981-12-03  3000    NA     20     800 

     


    5. R sqldf Package

    서브쿼리를 사용하여 관리자(‘mgr’) 사원번호 목록에 존재하는 사원번호(‘empno’)를 선택하여서 관리자 역할을 수행하는 직원을 선택하고, 상관서브쿼리를 사용하여서 관리자 본인이 관리하고 있는 부서 직원 평균 급여보다 더 많은 급여를 수령하는 관리자 정보를 출력한다.

     

    R Programming
    %%R
    
    sqldf(" select ename, sal from emp e 
            where  empno in (select mgr from emp where mgr is not null) 
              and  e.sal > (select avg(sal) from emp where mgr = e.empno);")

     

    Results
      ename  sal
    1 BLAKE 2850
    2 CLARK 2450
    3 SCOTT 3000
    4  KING 5000
    5  FORD 3000

     


    emp 테이블의 사원번호(‘empno’)와 중복을 제거한 관리자(‘mgr’) 사원번호를 기준으로 결합하여서 관리자 역할을 수행하는 사원들을 선택하고, emp테이블에서 관리자 사원번호를 기준으로 평균 급여를 계산한 결과(관리자 산하에 근무하는 직원의 평균 급여)를 추가로 Inner Join을 수행하여서 관리자의 급여가 본인이 관리하고 있는 부서 직원 평균 급여보다 더 많은 급여를 수령하는 관리자 정보를 출력한다.

     

    R Programming
    %%R
    
    sqldf("SELECT emp.* 
           FROM   emp,
                  (select distinct MGR from emp) b,
                  (select mgr, avg(sal) sal_avg from emp group by mgr) c
           WHERE  emp.empno = b.mgr
             and  emp.empno = c.mgr
             and  emp.sal   > sal_avg")

     

    Results
      empno ename       job  mgr   hiredate  sal comm deptno
    1  7698 BLAKE   MANAGER 7839 1981-03-01 2850   NA     30
    2  7782 CLARK   MANAGER 7839 1981-01-09 2450   NA     10
    3  7788 SCOTT   ANALYST 7566 1982-12-09 3000   NA     20
    4  7839  KING PRESIDENT   NA 1981-11-17 5000   NA     10
    5  7902  FORD   ANALYST 7566 1981-12-03 3000   NA     20

     


    6. Python pandasql Package

    서브쿼리를 사용하여 관리자(‘mgr’) 사원번호 목록에 존재하는 사원번호(‘empno’)를 선택하여서 관리자 역할을 수행하는 직원을 선택하고, 상관서브쿼리를 사용하여서 관리자 본인이 관리하고 있는 부서 직원 평균 급여보다 더 많은 급여를 수령하는 관리자 정보를 출력한다.

     

    Python Programming
    ps.sqldf(" select ename, sal                                           \
               from   emp e                                                \
               where  empno in (select mgr from emp where mgr is not null) \
                 and  e.sal>(select avg(sal) from emp where mgr=e.empno);")

     


    Results
      ename sal
    0 BLAKE 2850
    1 CLARK 2450
    2 SCOTT 3000
    3 KING 5000
    4 FORD 3000

     


     

    Python Programming
    ps.sqldf("SELECT emp.*                                                 \
              FROM   emp,                                                  \
                     (select distinct MGR from emp) b,                     \
                     (select mgr,avg(sal) sal_avg from emp group by mgr) c \
              WHERE  emp.empno = b.mgr                                     \
                and  emp.empno = c.mgr                                     \
                and  emp.sal   > sal_avg")

     


    Results
      empno ename job mgr hiredate sal comm deptno
    0 7698 BLAKE MANAGER 7839.0 1981/03/01 2850 None 30
    1 7782 CLARK MANAGER 7839.0 1981/01/09 2450 None 10
    2 7788 SCOTT ANALYST 7566.0 1982/12/09 3000 None 20
    3 7839 KING PRESIDENT NaN 1981/11/17 5000 None 10
    4 7902 FORD ANALYST 7566.0 1981/12/03 3000 None 20

     


    7. R data.table Package

    emp 테이블에서 사원번호(‘empno’)가 관리자(‘mgr’) 사원번호에 존재하는 관리자들의 데이터를 선택하고, emp 테이블에서 관리자(‘mgr’) 사원번호별 평균 급여를 계산한 후 2개의 추출 결과를 inner Join으로 결합하여 관리자의 급여가 담당하고 있는 부서 직원들의 평균 급여보다 더 많이 수령하는 관리자들을 추출한다.

     

    R Programming
    %%R
    
    DT          <- data.table(emp)
    dept_DT     <- data.table(dept)
    salgrade_DT <- data.table(salgrade)
    
    merge( DT[ DT[,(empno %in% DT[]$mgr)  ] ], 
           DT[ , .(sal_mean = mean(sal)), by = .(mgr)],
           by.x=c("empno"),
           by.y=c("mgr"),all=F)[sal > sal_mean]

     

    Results
       empno ename       job  mgr   hiredate  sal comm deptno sal_mean
    1:  7698 BLAKE   MANAGER 7839 1981-03-01 2850   NA     30 1310.000
    2:  7782 CLARK   MANAGER 7839 1981-01-09 2450   NA     10 1300.000
    3:  7788 SCOTT   ANALYST 7566 1982-12-09 3000   NA     20 1100.000
    4:  7839  KING PRESIDENT   NA 1981-11-17 5000   NA     10 2758.333
    5:  7902  FORD   ANALYST 7566 1981-12-03 3000   NA     20  800.000

     


    8. SAS Proc SQL

    서브쿼리를 사용하여 관리자(‘mgr’) 사원번호 목록에 존재하는 사원번호(‘empno’)를 선택하여서 관리자 역할을 수행하는 직원을 선택하고, 상관서브쿼리를 사용하여서 관리자 본인이 관리하고 있는 부서 직원 평균 급여보다 더 많은 급여를 수령하는 관리자 정보를 출력한다.

     

    SAS Programming
    %%SAS sas
    
    PROC SQL;
      CREATE TABLE STATSAS_1 AS
        select ename, sal 
        from   emp e 
        where  empno in (select mgr from emp) 
          and  e.sal > (select avg(sal) from emp where mgr=e.empno);
    QUIT;
    PROC PRINT;RUN;

     


    Results
    OBS ename sal
    1 BLAKE 2850
    2 CLARK 2450
    3 SCOTT 3000
    4 KING 5000
    5 FORD 3000

     


    9. SAS Data Step

     

    SAS Programming
    %%SAS sas
    
    PROC SORT DATA=emp OUT=EMP_1(RENAME=( EMPNO = MGR_EMPNO));
         BY EMPNO;
    RUN;
    
    PROC SORT DATA=emp OUT=EMP_2(RENAME=( MGR  = MGR_EMPNO)
                                           KEEP = MGR) NODUPKEY;
         BY MGR;
    RUN;
    
    DATA STATSAS_2;
     MERGE EMP_1(IN=A) EMP_2(IN=B);
         BY MGR_EMPNO;
         IF A AND B THEN OUTPUT;
         KEEP ENAME MGR_EMPNO SAL;
    RUN;
    
    PROC SUMMARY DATA=EMP NWAY;
         CLASS MGR;
         VAR SAL;
         OUTPUT OUT=EMP_S1(DROP=_:) MEAN=SAL_MEAN;
    RUN;
    
    PROC SORT DATA=STATSAS_2 OUT=EMP_3;
         BY MGR_EMPNO;
    RUN;
    
    PROC SORT DATA=EMP_S1 OUT=EMP_S2(RENAME=( MGR  = MGR_EMPNO) ) NODUPKEY;
         BY MGR;
    RUN;
    
    DATA STATSAS_2;
     MERGE EMP_3(IN=A) EMP_S2(IN=B);
         BY MGR_EMPNO;
         IF A AND B;
         IF SAL > SAL_MEAN THEN OUTPUT;
    RUN;
    PROC PRINT;RUN;

     


    Results
    OBS MGR_EMPNO ename sal SAL_MEAN
    1 7698 BLAKE 2850 1310
    2 7782 CLARK 2450 1300
    3 7788 SCOTT 3000 1100
    4 7839 KING 5000 2758
    5 7902 FORD 3000 800

     


    10. Python Dfply Package

     

    Python Programming
    # [참고] 함수 사용. (52번 예제 참고) : AttributeError: 'DataFrame' object has no attribute 'ix'
    @pipe
    def pull_list(df, column=-1):
        return df.loc[:, column]
    
    @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 >> \
      filter_by(X.empno.isin( emp >> select(X.mgr) >> pull_list("mgr")))                                                          >> \
      inner_join_merge( (emp >> group_by('mgr') >> summarize(sal_mean = X.sal.mean())) ,left_on  = ["empno"], right_on = ["mgr"]) >> \
      filter_by(X.sal > X.sal_mean)                                                                                               >> \
      select(~X.job, ~X.hiredate, ~X.comm)     

     


    Results
      empno ename mgr_x sal deptno mgr_y sal_mean
    1 7698 BLAKE 7839.0 2850 30 7698.0 1310.000000
    2 7782 CLARK 7839.0 2450 10 7782.0 1300.000000
    3 7788 SCOTT 7566.0 3000 20 7788.0 1100.000000
    4 7839 KING NaN 5000 10 7839.0 2758.333333
    5 7902 FORD 7566.0 3000 20 7902.0 800.000000

     


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

    반응형

    댓글