본문 바로가기

Programming/SQL

9. 연습(3)

Edit

9. 연습(3)

1. 그룹(GROUP)의 6번 문제에서 [다음 그림과 같이 직원들의 부서 이동 과정을 출력하시오] 라는 문제를 풀었다.

SELECT DE.EMP_NO, GROUP_CONCAT(DE.DEPT_NO SEPARATOR ' > ' ) PATH
FROM DEPT_EMP DE
GROUP BY DE.EMP_NO
HAVING COUNT(*)>1
ORDER BY COUNT(*) DESC;


2. 이 문제는 좀 더 많은 설명과 구현이 필요한 SQL문이다. 먼저, 다음 그림과 같이 실행 결과에서 직원의 이름과 부서 명이 필요하다.

NOTE : 아래의 설명을 읽는 것도 좋겠지만 위와 같이 출력되게 하는 SQL문을 직접 작성해 보면 실력향상에 도움이 될 것이다.

SELECT DE.EMP_NO
, E.FIRST_NAME
, E.LAST_NAME
, GROUP_CONCAT(D.DEPT_NAME SEPARATOR ' > ' ) PATH
FROM DEPT_EMP DE
INNER JOIN DEPARTMENTS D ON D.DEPT_NO=DE.DEPT_NO
INNER JOIN EMPLOYEES E ON E.EMP_NO=DE.EMP_NO
GROUP BY DE.EMP_NO, E.FIRST_NAME, E.LAST_NAME
HAVING COUNT(*)>1
ORDER BY COUNT(*) DESC;

NOTE : 직원의 이름(FIRST_NAME, LAST_NAME)과 부서 명(DEPT_NAME)이 출력되기 위해서는 직원 테이블(EMPLOYEES)과 부서 테이블(DEPARTMENTS)을 추가해 주면 된다.
그리고, 직원 정보로 GROUP화하고 부서 명(DEPT_NAME)을 묶으면 된다.
여기서 생각해야 할 것이 GROUP으로 직원 정보를 사용하는 것이다.
직원명외에 생일을 추가한다고 할 경우 GROUP에 생일 필드를 추가해야 한다.
GROUP에 가변길이 문자열을 많은 추가하는 것은 SQL 성능(속도)상 추천되지 않는다.
다음과 같이 서브쿼리(SubQuery)를 이용하는 것이 바람직하다.

SELECT DS.EMP_NO, E.FIRST_NAME, E.LAST_NAME, PATH
FROM (
SELECT DE.EMP_NO
, GROUP_CONCAT(D.DEPT_NAME SEPARATOR ' > ' ) PATH
, COUNT(*) CNT
FROM DEPT_EMP DE
INNER JOIN DEPARTMENTS D ON D.DEPT_NO=DE.DEPT_NO
GROUP BY DE.EMP_NO
HAVING COUNT(*)>1
) DS
INNER JOIN EMPLOYEES E ON E.EMP_NO=DS.EMP_NO
ORDER BY CNT DESC;

NOTE : 부서는 조인을 이용하지만 개인정보는 서브쿼리를 사용하는 것이 좋다.
GROUP에 사용된 다는 것은 인덱스가 필요하다는 의미로 좀 더 복잡한 처리가 필요한 것도 있지만, 단순하게 데이터 개수의 의미도 있다.
조인을 사용할 경우 직원 수가 약 30만(300,024)이고, 부서 할당 정보가 약 33만 (331,603)이니 30만 * 33만의 처리가 발생한다.
서브 쿼리로 실행하면, 다음 SQL에서 알수 있듯이 처리 개수가 3만(31,579)개로 줄어든다.
부서 이동이 발생한 직원들만 처리하기 때문이며, 당연이 조인시 발생하는 처리 수도 줄어 든다.

SELECT COUNT(*)
FROM (
SELECT DE.EMP_NO
, GROUP_CONCAT(D.DEPT_NAME SEPARATOR ' > ' ) PATH
, COUNT(*) CNT
FROM DEPT_EMP DE
INNER JOIN DEPARTMENTS D ON D.DEPT_NO=DE.DEPT_NO
GROUP BY DE.EMP_NO
HAVING COUNT(*)>1
) DS

NOTE : 제대로 완성 시키려면, 현재 근무하는 직원만 출력해야 한다.
현재 근무하는 직원은 부서 할당(DEPT_EMP) 테이블에 근무 종료(TO_DATE)가 9999-01-01인 직원들이므로 다음과 같이 두개의 부서 할당 테이블이 필요하다.
하나는 현재 근무 중인 직원을 가져오는 테이블(DEPT_EMP DE1),
나머지는 부서 이동 정보를 가져오는 테이블(DEPT_EMP DE2)이다.

SELECT DS.EMP_NO, E.FIRST_NAME, E.LAST_NAME, PATH
FROM (
SELECT DE1.EMP_NO
, GROUP_CONCAT(D.DEPT_NAME SEPARATOR ' > ') PATH
, COUNT(*) CNT
FROM DEPT_EMP DE1
INNER JOIN DEPT_EMP DE2 ON DE2.EMP_NO=DE1.EMP_NO
INNER JOIN DEPARTMENTS D ON D.DEPT_NO=DE2.DEPT_NO
WHERE DE1.TO_DATE='9999-01-01'
GROUP BY DE1.EMP_NO
HAVING COUNT(*)>1
) DS
INNER JOIN EMPLOYEES E ON E.EMP_NO=DS.EMP_NO
ORDER BY CNT DESC;

NOTE : 부서 테이블과의 조인은 D.DEPT_NO=DE2.DEPT_NO
부서 이동 정보를 가져오는 테이블은 DEPT_EMP DE2 이다.


출처 : SW 개발이 좋은 사람

%23%23%23%209.%20%uC5F0%uC2B5%283%29%0A%0A@%28SQL%29%5Btistory%2C%20SQL%5D%0A%0A-%20%5B**%uC0D8%uD50C%20%uB370%uC774%uD130%20%uBCA0%uC774%uC2A4%20%uAC1C%uC694**%5D%28http%3A//youssol.tistory.com/26%29%0A-%20%uC55E%uC11C%20%uBD80%uC11C%uBCC4%uB85C%20%uC9C1%uC6D0%20%uC218%uB97C%20%uAD6C%uD558%uB294%20%uBB38%uC81C%uB97C%203%uAC00%uC9C0%20%uBC29%uBC95%uC73C%uB85C%20%uC0B4%uD3B4%20%uBCF4%uC558%uB2E4.%0A-%20%5B**%uC870%uC778%28Join%29%20**%5D%28http%3A//youssol.tistory.com/29%29%20**4%uBC88**%2C%20%5B**%uC11C%uBE0C%uCFFC%uB9AC%28SubQuery%29**%5D%28http%3A//youssol.tistory.com/30%29%20**1%uBC88**%uACFC%20**4%uBC88**%20%uBB38%uC81C%uB85C%20%0A-%20%uC815%uB9AC%uD558%uB294%20%uC758%uBBF8%uC5D0%uC11C%20%uBD80%uC11C%20%uC774%uB3D9%20%uBB38%uC81C%uB97C%20%uC774%uC6A9%uD558%uC5EC%20%uB2E4%uC74C%uACFC%20%uAC19%uC774%20%uC815%uB9AC%uD558%uC600%uB2E4.%0A%0A**1.%20%20%5B%uADF8%uB8F9%28GROUP%29%5D%28http%3A//youssol.tistory.com/28%29%uC758%206%uBC88%20%uBB38%uC81C%uC5D0%uC11C%20%5B%uB2E4%uC74C%20%uADF8%uB9BC%uACFC%20%uAC19%uC774%20%uC9C1%uC6D0%uB4E4%uC758%20%uBD80%uC11C%20%uC774%uB3D9%20%uACFC%uC815%uC744%20%uCD9C%uB825%uD558%uC2DC%uC624%5D%20%uB77C%uB294%20%uBB38%uC81C%uB97C%20%uD480%uC5C8%uB2E4.**%0A%21%5BAlt%20text%5D%28./1.png%29%0A%60%60%60sql%0ASELECT%20DE.EMP_NO%2C%20GROUP_CONCAT%28DE.DEPT_NO%20SEPARATOR%20%27%20%3E%20%27%20%29%20PATH%0A%20%20FROM%20DEPT_EMP%20DE%0A%20GROUP%20BY%20DE.EMP_NO%0AHAVING%20COUNT%28*%29%3E1%0A%20ORDER%20BY%20COUNT%28*%29%20DESC%3B%0A%60%60%60%0A%0A%3Cbr%3E%0A%0A**2.%20%uC774%20%uBB38%uC81C%uB294%20%uC880%20%uB354%20%uB9CE%uC740%20%uC124%uBA85%uACFC%20%uAD6C%uD604%uC774%20%uD544%uC694%uD55C%20SQL%uBB38%uC774%uB2E4.%20%uBA3C%uC800%2C%20%uB2E4%uC74C%20%uADF8%uB9BC%uACFC%20%uAC19%uC774%20%uC2E4%uD589%20%uACB0%uACFC%uC5D0%uC11C%20%uC9C1%uC6D0%uC758%20%uC774%uB984%uACFC%20%uBD80%uC11C%20%uBA85%uC774%20%uD544%uC694%uD558%uB2E4.**%0A%21%5BAlt%20text%5D%28./2.png%29%0A%3E%20**NOTE%20%3A%20**%uC544%uB798%uC758%20%uC124%uBA85%uC744%20%uC77D%uB294%20%uAC83%uB3C4%20%uC88B%uACA0%uC9C0%uB9CC%20%uC704%uC640%20%uAC19%uC774%20%uCD9C%uB825%uB418%uAC8C%20%uD558%uB294%20SQL%uBB38%uC744%20%uC9C1%uC811%20%uC791%uC131%uD574%20%uBCF4%uBA74%20%uC2E4%uB825%uD5A5%uC0C1%uC5D0%20%uB3C4%uC6C0%uC774%20%uB420%20%uAC83%uC774%uB2E4.%0A%60%60%60sql%0ASELECT%20DE.EMP_NO%0A%09%20%2C%20E.FIRST_NAME%0A%09%20%2C%20E.LAST_NAME%0A%09%20%2C%20GROUP_CONCAT%28D.DEPT_NAME%20SEPARATOR%20%27%20%3E%20%27%20%29%20PATH%0A%20%20FROM%20DEPT_EMP%20DE%0A%20INNER%20JOIN%20DEPARTMENTS%20D%20ON%20D.DEPT_NO%3DDE.DEPT_NO%0A%20INNER%20JOIN%20EMPLOYEES%20E%20ON%20E.EMP_NO%3DDE.EMP_NO%0A%20GROUP%20BY%20DE.EMP_NO%2C%20E.FIRST_NAME%2C%20E.LAST_NAME%0AHAVING%20COUNT%28*%29%3E1%0A%20ORDER%20BY%20COUNT%28*%29%20DESC%3B%0A%60%60%60%0A%3E%20**NOTE%20%3A%20**%uC9C1%uC6D0%uC758%20%uC774%uB984%28FIRST_NAME%2C%20LAST_NAME%29%uACFC%20%uBD80%uC11C%20%uBA85%28DEPT_NAME%29%uC774%20%uCD9C%uB825%uB418%uAE30%20%uC704%uD574%uC11C%uB294%20%uC9C1%uC6D0%20%uD14C%uC774%uBE14%28EMPLOYEES%29%uACFC%20%uBD80%uC11C%20%uD14C%uC774%uBE14%28DEPARTMENTS%29%uC744%20%uCD94%uAC00%uD574%20%uC8FC%uBA74%20%uB41C%uB2E4.%0A%3E%20%uADF8%uB9AC%uACE0%2C%20%uC9C1%uC6D0%20%uC815%uBCF4%uB85C%20GROUP%uD654%uD558%uACE0%20%uBD80%uC11C%20%uBA85%28DEPT_NAME%29%uC744%20%uBB36%uC73C%uBA74%20%uB41C%uB2E4.%0A%3E%20%uC5EC%uAE30%uC11C%20%uC0DD%uAC01%uD574%uC57C%20%uD560%20%uAC83%uC774%20GROUP%uC73C%uB85C%20%uC9C1%uC6D0%20%uC815%uBCF4%uB97C%20%uC0AC%uC6A9%uD558%uB294%20%uAC83%uC774%uB2E4.%0A%3E%20%uC9C1%uC6D0%uBA85%uC678%uC5D0%20%uC0DD%uC77C%uC744%20%uCD94%uAC00%uD55C%uB2E4%uACE0%20%uD560%20%uACBD%uC6B0%20GROUP%uC5D0%20%uC0DD%uC77C%20%uD544%uB4DC%uB97C%20%uCD94%uAC00%uD574%uC57C%20%uD55C%uB2E4.%0A%3E%20GROUP%uC5D0%20%uAC00%uBCC0%uAE38%uC774%20%uBB38%uC790%uC5F4%uC744%20%uB9CE%uC740%20%uCD94%uAC00%uD558%uB294%20%uAC83%uC740%20SQL%20%uC131%uB2A5%28%uC18D%uB3C4%29%uC0C1%20%uCD94%uCC9C%uB418%uC9C0%20%uC54A%uB294%uB2E4.%0A%3E%20%uB2E4%uC74C%uACFC%20%uAC19%uC774%20%uC11C%uBE0C%uCFFC%uB9AC%28SubQuery%29%uB97C%20%uC774%uC6A9%uD558%uB294%20%uAC83%uC774%20%uBC14%uB78C%uC9C1%uD558%uB2E4.%0A%60%60%60sql%0ASELECT%20DS.EMP_NO%2C%20E.FIRST_NAME%2C%20E.LAST_NAME%2C%20PATH%0A%20%20FROM%20%28%0A%20%20%20%20%20%20%20%20SELECT%20DE.EMP_NO%0A%09%20%20%20%20%20%20%20%20%20%2C%20GROUP_CONCAT%28D.DEPT_NAME%20SEPARATOR%20%27%20%3E%20%27%20%29%20PATH%0A%09%20%20%20%20%20%20%20%20%20%2C%20COUNT%28*%29%20CNT%0A%20%20%20%20%20%20%20%20%20%20FROM%20DEPT_EMP%20DE%0A%20%20%20%20%20%20%20%20%20INNER%20JOIN%20DEPARTMENTS%20D%20ON%20D.DEPT_NO%3DDE.DEPT_NO%0A%20%20%20%20%20%20%20%20%20GROUP%20BY%20DE.EMP_NO%0A%20%20%20%20%20%20%20%20HAVING%20COUNT%28*%29%3E1%0A%09%20%20%20%29%20DS%0A%20INNER%20JOIN%20EMPLOYEES%20E%20ON%20E.EMP_NO%3DDS.EMP_NO%0A%20ORDER%20BY%20CNT%20DESC%3B%0A%60%60%60%0A%3E%20**NOTE%20%3A%20**%20%uBD80%uC11C%uB294%20%uC870%uC778%uC744%20%uC774%uC6A9%uD558%uC9C0%uB9CC%20%uAC1C%uC778%uC815%uBCF4%uB294%20%uC11C%uBE0C%uCFFC%uB9AC%uB97C%20%uC0AC%uC6A9%uD558%uB294%20%uAC83%uC774%20%uC88B%uB2E4.%0A%3E%20GROUP%uC5D0%20%uC0AC%uC6A9%uB41C%20%uB2E4%uB294%20%uAC83%uC740%20%uC778%uB371%uC2A4%uAC00%20%uD544%uC694%uD558%uB2E4%uB294%20%uC758%uBBF8%uB85C%20%uC880%20%uB354%20%uBCF5%uC7A1%uD55C%20%uCC98%uB9AC%uAC00%20%uD544%uC694%uD55C%20%uAC83%uB3C4%20%uC788%uC9C0%uB9CC%2C%20%uB2E8%uC21C%uD558%uAC8C%20%uB370%uC774%uD130%20%uAC1C%uC218%uC758%20%uC758%uBBF8%uB3C4%20%uC788%uB2E4.%0A%3E%20%uC870%uC778%uC744%20%uC0AC%uC6A9%uD560%20%uACBD%uC6B0%20%uC9C1%uC6D0%20%uC218%uAC00%20%uC57D%2030%uB9CC%28300%2C024%29%uC774%uACE0%2C%20%uBD80%uC11C%20%uD560%uB2F9%20%uC815%uBCF4%uAC00%20%uC57D%2033%uB9CC%20%28331%2C603%29%uC774%uB2C8%2030%uB9CC%20*%2033%uB9CC%uC758%20%uCC98%uB9AC%uAC00%20%uBC1C%uC0DD%uD55C%uB2E4.%0A%3E%20%uC11C%uBE0C%20%uCFFC%uB9AC%uB85C%20%uC2E4%uD589%uD558%uBA74%2C%20%uB2E4%uC74C%20SQL%uC5D0%uC11C%20%uC54C%uC218%20%uC788%uB4EF%uC774%20%uCC98%uB9AC%20%uAC1C%uC218%uAC00%203%uB9CC%2831%2C579%29%uAC1C%uB85C%20%uC904%uC5B4%uB4E0%uB2E4.%0A%3E%20%uBD80%uC11C%20%uC774%uB3D9%uC774%20%uBC1C%uC0DD%uD55C%20%uC9C1%uC6D0%uB4E4%uB9CC%20%uCC98%uB9AC%uD558%uAE30%20%uB54C%uBB38%uC774%uBA70%2C%20%uB2F9%uC5F0%uC774%20%uC870%uC778%uC2DC%20%uBC1C%uC0DD%uD558%uB294%20%uCC98%uB9AC%20%uC218%uB3C4%20%uC904%uC5B4%20%uB4E0%uB2E4.%0A%60%60%60sql%0ASELECT%20COUNT%28*%29%0A%20%20FROM%20%28%0A%20%20%20%20%20%20%20%20SELECT%20DE.EMP_NO%0A%09%09%20%20%20%20%20%2C%20GROUP_CONCAT%28D.DEPT_NAME%20SEPARATOR%20%27%20%3E%20%27%20%29%20PATH%0A%09%09%20%20%20%20%20%2C%20COUNT%28*%29%20CNT%0A%20%20%20%20%20%20%20%20%20%20FROM%20DEPT_EMP%20DE%0A%20%20%20%20%20%20%20%20%20INNER%20JOIN%20DEPARTMENTS%20D%20ON%20D.DEPT_NO%3DDE.DEPT_NO%0A%20%20%20%20%20%20%20%20%20GROUP%20BY%20DE.EMP_NO%0A%20%20%20%20%20%20%20%20HAVING%20COUNT%28*%29%3E1%0A%09%20%20%20%29%20DS%0A%60%60%60%0A%3E%20**NOTE%20%3A%20**%20%uC81C%uB300%uB85C%20%uC644%uC131%20%uC2DC%uD0A4%uB824%uBA74%2C%20%uD604%uC7AC%20%uADFC%uBB34%uD558%uB294%20%uC9C1%uC6D0%uB9CC%20%uCD9C%uB825%uD574%uC57C%20%uD55C%uB2E4.%0A%3E%20%uD604%uC7AC%20%uADFC%uBB34%uD558%uB294%20%uC9C1%uC6D0%uC740%20%uBD80%uC11C%20%uD560%uB2F9%28DEPT_EMP%29%20%uD14C%uC774%uBE14%uC5D0%20%uADFC%uBB34%20%uC885%uB8CC%28TO_DATE%29%uAC00%209999-01-01%uC778%20%uC9C1%uC6D0%uB4E4%uC774%uBBC0%uB85C%20%uB2E4%uC74C%uACFC%20%uAC19%uC774%20%uB450%uAC1C%uC758%20%uBD80%uC11C%20%uD560%uB2F9%20%uD14C%uC774%uBE14%uC774%20%uD544%uC694%uD558%uB2E4.%0A%3E%20%uD558%uB098%uB294%20%uD604%uC7AC%20%uADFC%uBB34%20%uC911%uC778%20%uC9C1%uC6D0%uC744%20%uAC00%uC838%uC624%uB294%20%uD14C%uC774%uBE14%28DEPT_EMP%20DE1%29%2C%0A%3E%20%uB098%uBA38%uC9C0%uB294%20%uBD80%uC11C%20%uC774%uB3D9%20%uC815%uBCF4%uB97C%20%uAC00%uC838%uC624%uB294%20%uD14C%uC774%uBE14%28DEPT_EMP%20DE2%29%uC774%uB2E4.%0A%60%60%60sql%0ASELECT%20DS.EMP_NO%2C%20E.FIRST_NAME%2C%20E.LAST_NAME%2C%20PATH%0A%20%20FROM%20%28%0A%20%20%20%20%20%20%20%20SELECT%20DE1.EMP_NO%0A%09%20%20%20%20%20%20%20%20%20%2C%20GROUP_CONCAT%28D.DEPT_NAME%20SEPARATOR%20%27%20%3E%20%27%29%20PATH%0A%09%20%20%20%20%20%20%20%20%20%2C%20COUNT%28*%29%20CNT%0A%20%20%20%20%20%20%20%20%20%20FROM%20DEPT_EMP%20DE1%0A%20%20%20%20%20%20%20%20%20INNER%20JOIN%20DEPT_EMP%20DE2%20ON%20DE2.EMP_NO%3DDE1.EMP_NO%0A%20%20%20%20%20%20%20%20%20INNER%20JOIN%20DEPARTMENTS%20D%20ON%20D.DEPT_NO%3DDE2.DEPT_NO%0A%20%20%20%20%20%20%20%20%20WHERE%20DE1.TO_DATE%3D%279999-01-01%27%0A%20%20%20%20%20%20%20%20%20GROUP%20BY%20DE1.EMP_NO%0A%20%20%20%20%20%20%20%20HAVING%20COUNT%28*%29%3E1%0A%09%20%20%20%29%20DS%0A%20INNER%20JOIN%20EMPLOYEES%20E%20ON%20E.EMP_NO%3DDS.EMP_NO%0A%20ORDER%20BY%20CNT%20DESC%3B%0A%60%60%60%0A%3E%20**NOTE%20%3A%20**%20%uBD80%uC11C%20%uD14C%uC774%uBE14%uACFC%uC758%20%uC870%uC778%uC740%20**D.DEPT_NO%3DDE2.DEPT_NO**%20%0A%3E%20%uBD80%uC11C%20%uC774%uB3D9%20%uC815%uBCF4%uB97C%20%uAC00%uC838%uC624%uB294%20%uD14C%uC774%uBE14%uC740%20**DEPT_EMP%20DE2**%20%uC774%uB2E4.%0A%0A%3Cbr%3E%0A%0A**%uCD9C%uCC98%20%3A%20**%20%5BSW%20%uAC1C%uBC1C%uC774%20%uC88B%uC740%20%uC0AC%uB78C%5D%28http%3A//forest71.tistory.com/%29

'Programming > SQL' 카테고리의 다른 글

대용량 테이블 삭제 방법  (0) 2017.05.02
8. 연습(2)  (0) 2017.03.11
7. 연습(1)  (0) 2017.03.11
6. 실습(4) - SubQuery  (0) 2017.02.28
5. 실습(3) - Join  (0) 2017.02.28