데이터베이스 실습문제

권재현·2021년 4월 18일
0

문제풀이

목록 보기
8/8
post-thumbnail

4월16일 문제풀이

내가 풀었던 코드와 선생님이 적어주신 코드를 비교 분석하면서 차이점을 발견해 다음에 풀때는 풀이 적용할 수 있게 하는 것 이 목적이다.

사용 테이블 HR

1.난이도 하 - 부하직원이 가장 많은 상급자를 구하시오.

--내코드

SELECT E.*
FROM (SELECT MANAGER_ID,COUNT(*),
        RANK () OVER (ORDER BY COUNT(*) DESC ) AS RNK
        FROM EMPLOYEES
        GROUP BY MANAGER_ID) M INNER JOIN EMPLOYEES E
                            ON M.MANAGER_ID = E.EMPLOYEE_ID 
WHERE RNK = 1    
;

--선생님 코드

SELECT E.FIRST_NAME
FROM EMPLOYEES E INNER JOIN (SELECT MANAGER_ID,
                             RANK()OVER(ORDER BY COUNT(*) DESC) AS RNK
                              FROM EMPLOYEES 
                              GROUP BY MANAGER_ID ) M
                        ON E.EMPLOYEE_ID = M.MANAGER_ID
                    AND M.RNK = 1
;

 문제가 간단해 선생님과 나의 코드가 큰차이는 없지만, 눈에 띄는 요소는 바로 마지막에 부하직원이 가장많은 상급자를 구하기 위해, 순차함수을 활용해서 순위를 구했고 , 1위로 나온 상급자가 조건에 부합한다.

  서브쿼리는 부하직원 수에 따른 상급자 순위고, 우리가 필요한 것은 1위다. 위에 코드에서 확인 할 수 있듯이 나는 where에 조건을 추가했고, 샘은 on 조건 다음에 and로 추가했다. 샘은 처음 실행 할 때 from에서 이미 조건처리가 끝나고, 나는 where 까지 와야 조건처리가 마무리된다.

 사실 지금 데이터양이 많지 않아서 크게 차이는 안나겠지만, 데이터가 1억개 정도 있다면, 엄청난 차이를 가져올 것이다. 그렇기 때문에 from에서 가능한 것은 다처리하자.

2.난이도 중 - 업무나 부서 변동이 있었던 사원들의 급여평균을 구하시오.

--내코드

SELECT ROUND(AVG(E2.SALARY),2)
FROM EMPLOYEES E2 INNER JOIN (SELECT DISTINCT E.EMPLOYEE_ID
                            FROM EMPLOYEES E INNER JOIN JOB_HISTORY J
                                ON E.EMPLOYEE_ID = J.EMPLOYEE_ID ) J2
                 ON E2.EMPLOYEE_ID = J2.EMPLOYEE_ID
;

--선생님 코드

SELECT AVG(E.SALARY) AS AVG_SAL
FROM EMPLOYEES E INNER JOIN ( SELECT DISTINCT EMPLOYEE_ID   
                                FROM JOB_HISTORY ) J
                            ON E.EMPLOYEE_ID = J.EMPLOYEE_ID
;

  새로운 테이블이 등장한다 바로 JOB_HISTORY 업무나 부서 변동을 기록한 테이블이다. 이 테이블에 중복이 존재하는데, 나는 EMPLOYEES 에 붙이고 제외했고, 샘은 안붙이고 제외를 했다.

사실 지금 보면 내가 JOB_HISTORY을 그냥 보지않고 테이블들을 제대로 봤다면, 나역시도 선생님같이 했을 것이다. 오늘 다시한번 깨달은 사실이지만 테이블은 살펴보라고 하시는 이야기 점점 와닿고 있다. 테이블을  꼭 보자 

3.난이도 상 - 원수 1,2등인 부서들의 급여 평균을 구하고, 그 평균의 차이를 구하시오.

--내 코드
SELECT ABS( AVG(CASE WHEN D2.RNK =1
           THEN E2.SALARY
           ELSE NULL
           END ) -  AVG( CASE WHEN D2.RNK =2
                       THEN E2.SALARY
                       ELSE NULL
                       END)) AS RESULT
FROM EMPLOYEES E2 INNER JOIN (SELECT E.DEPARTMENT_ID,COUNT(*),
                            RANK() OVER (ORDER BY COUNT(*) DESC) AS RNK
                                FROM EMPLOYEES E 
                                INNER JOIN DEPARTMENTS D 
                                   ON E.DEPARTMENT_ID = D.DEPARTMENT_ID
                                    GROUP BY   E.DEPARTMENT_ID ) D2
                           ON E2.DEPARTMENT_ID = D2.DEPARTMENT_ID                                                                          
;

--선생님 코드
SELECT MAX(AVG_SAL) - MIN(AVG_SAL) AS CHA  

FROM
       (SELECT DEPARTMENT_ID, AVG(SALARY) AS AVG_SAL,
               RANK() OVER(ORDER BY COUNT(*) DESC ) AS RNK
       FROM EMPLOYEES
       GROUP BY DEPARTMENT_ID ) E
WHERE E.RNK IN (1,2)
;

 선생님이 풀이 해주실 때 충격의 도가니였던 문제였다. 이 문제의 교훈 역시 문제에서 주어진 조건을 잘 읽고 파악했으면, 불필요한 이너조인을 안사용할 수 있었고, 그다음 급여평균을 확인하고 금액까지 확인했으면 굳이 CASE 문 쓰기 보다는 샘처러 MAX 와 MIN을 통해 저렇게 간편하게 사용할 수 있었는데, 아쉬웠다. 뭐 한편으로는 저 문제를 풀 당시에 내가 가진 최선을 다해서 풀었을 수 도 있지만, 내가 생각하기 편한방법으로 한게 아니였을 까? 라는 생각이든다.

데이터베이스는 이번주부터는 확실히 자신감이 조금씩 생기고 있다.
오늘 희두형과 오전에 서로의 코드를 보면서 느낀 거지만, 이제 나만의 생각이나 정리하는 방식이 생긴것 같은데, 그걸을 조금 경계하면서 문제가 주는 조건들을 다시한번 생각하면서, 어떻게 효율적을 데이터를 뽑아낼 수 있을 까 풀기전에 생각하는 습관을 들여보자

profile
호텔리어 출신 비전공자

0개의 댓글