Day25

Day25

1.SET 연산자를 이용해서 테이블간의 연산을 구현 할 수 있다. (합집합,교집합,베타집합....)

2.SubQuery(서브쿼리)에 대한 개념을 이해하고 설명 할 수 있다.

3.서브쿼리를 구현할 수 있고 조인과 구분할 수 있다.

4.단일 행 서브쿼리, 다중행 서브쿼리와 연산자를 이해하고 활용할 수 있다.

SubQuery

하나의 쿼리가 다른 쿼리에 포함되는 구조
다른 쿼리에 포함된 내부 쿼리(서브쿼리)는 외부 쿼리(메인쿼리)에 사용될 값을 반환하는 역할

[형식]
SELECT
FROM
WHERE expr operator (
SELECT
FROM
WHERE....
);

1)서브쿼리는 일반적인 SQL구문과 동일(별도 형식이 지정되어 있지 않다.)
2)SELECT ,FROM,WHERE,HAVING 절 등에서 사용이 가능하다.
3)서브쿼리는 ()로 묶여있다.
4)서브쿼리안에서는 ; 을 사용하지 않는다.
5)서브쿼리의 리턴하는 유형에 따라 연산자를 구분해서 사용한다.
6)단일행 서브쿼리 =,> , <,>=, <= , <> 등을 사용한다.
7)다중행 서브쿼리 IN,ANY,ALL 등을 사용한다.


문제

Q1.
USING(컬럼,컬럼)
ON : N개의 테이블 JOIN
EMPLOYEE(사원), JOB(직위), DEPARTMENT(부서),LOCATION(부서 위치)

[JOB_ID]DEPT_ID) [LOC_ID][LOCATION_ID]

직급이 대리이면서 아시아 지역에서 근무하는 사원의 이름과 부서이름을 출력 해보자.

SELECT EMP_NAME,DEPT_NAME
FROM EMPLOYEE 
JOIN JOB USING(JOB_ID)
JOIN DEPARTMENT USING(DEPT_ID)
JOIN LOCATION ON (LOC_ID = LOCATION_ID)
WHERE JOB_TITLE ='대리'
AND LOC_DESCRIBE LIKE '아시아%';


Q2. 사원의 이름과 근무지역, 부서명을 출력 해보자

SELECT EMP_NAME,LOC_DESCRIBE,DEPT_NAME
FROM EMPLOYEE
JOIN DEPARTMENT USING(DEPT_ID)
JOIN LOCATION ON (LOCATION_ID = LOC_ID);

Q3. SET Operato : 두 개 이상의 쿼리 결과를 하나로 결합시키는 연산자.
SELECT 절에 기술하는 컬럼 개수와 데이터 타입은 모든 쿼리에서 동일해야 한다.

-UNION : 양쪽 쿼리 결과를 모두 포함(중복된 결과는 1번만 표현)
-UNION ALL : 양쪽 쿼리 결과를 모두 포함(중복 결과도 모두 표현)
-INTERSECT : 양쪽 쿼리 결과에 모두 포함되는 행만 표현
-MINUS : 쿼리 1과,쿼리 2가 존재할 경우 쿼리1 결과에만 포함되고 쿼리2 결과에는 포함되지 않는 행만 표현.

모든 직원의 현재 ROLE과 이전 ROLE을 함께 출력 하되 사원의 ID와 ROLE_NAME을 출력하자.

SELECT EMP_ID,ROLE_NAME
FROM EMPLOYEE_ROLE
 UNION
SELECT EMP_ID,ROLE_NAME
FROM ROLE_HISTORY;
SELECT EMP_ID,ROLE_NAME
FROM EMPLOYEE_ROLE
 UNION ALL
SELECT EMP_ID,ROLE_NAME
FROM ROLE_HISTORY;

Q4.입사 후 현재 ROLE과 동일한 ROLE을 가졌던 적이 있는 직원을 조회해 보자.

SELECT EMP_ID,ROLE_NAME
FROM EMPLOYEE_ROLE
INTERSECT
SELECT EMP_ID,ROLE_NAME
FROM ROLE_HISTORY;

Q5.입사 후 현재 ROLE과 동일한 ROLE을 부여 받은적이 없는직원을 조회해 보자.

SELECT EMP_ID,ROLE_NAME
FROM EMPLOYEE_ROLE
MINUS
SELECT EMP_ID,ROLE_NAME
FROM ROLE_HISTORY;

Q6. SELECT 절에 기술하는 컬럼 개수와 데이터 타입은 모든 쿼리에서 동일해야 한다.
20번 부서 번호에 해당하는 사원의 이름과,JOB_ID,입사일과
20번 부서 번호에 해당하는 부서 번호와 부서ID의 데이터를 결합하고자 한다. (컬럼의 개수가 맞지 않을 경우 DUMMY Column을 사용)

SELECT EMP_NAME, JOB_ID, HIRE_DATE
FROM EMPLOYEE
WHERE DEPT_ID = '20'
UNION
SELECT DEPT_NAME,DEPT_ID,NULL
FROM DEPARTMENT
WHERE DEPT_ID = '20';

Q7. UNION 구문을 이용해서 50번 부서원을 관리자와 직원을 구분해 출력해라
사원의 번호,사원의 이름, 구분을 출력 하자.

EX) 124 정지현 직원
141 김예수 관리자

--- 50번 부서이면서 141사원 번호이면 관리자
50번 부서이면서 141MGR 번호가 아니면 직원.

SELECT EMP_ID,EMP_NAME, '관리자'AS 구분
FROM EMPLOYEE
WHERE EMP_ID = '141'
AND DEPT_ID = '50'
UNION
SELECT EMP_ID,EMP_NAME, '직원'AS 구분
FROM EMPLOYEE
WHERE MGR_ID = '141'
AND DEPT_ID = '50'
ORDER BY 3,1;     => 관리자 -> 직원 순으로 나열

SET - JOIN의 관계

Q8. SET - JOIN의 관계

---SET

SELECT EMP_ID,ROLE_NAME
FROM EMPLOYEE_ROLE
INTERSECT
SELECT EMP_ID, ROLE_NAME
FROM ROLE_HISTORY;

---JOIN

SELECT EMP_ID,ROLE_NAME
FROM EMPLOYEE_ROLE
JOIN ROLE_HISTORY USING(EMP_ID,ROLE_NAME);

SET - JOIN IN 관계

Q9.SET - JOIN IN 관계 : 사원의 이름과 직급을 출력 해보자.
--JOIN

SELECT EMP_NAME,JOB_TITLE 직급
FROM EMPLOYEE
JOIN JOB USING(JOB_ID)
WHERE JOB_TITLE IN('대리','사원')
ORDER BY 2,1;

--SET

SELECT EMP_NAME,'사원' 직급
FROM EMPLOYEE
JOIN JOB USING(JOB_ID)
WHERE JOB_TITLE= '사원'
UNION
SELECT EMP_NAME,'대리' 
FROM EMPLOYEE
JOIN JOB USING(JOB_ID)
WHERE JOB_TITLE= '대리'
ORDER BY 2,1;

SubQuery

Q10.SubQuery

JONES의 월급과 같은 월급을 받는 사원의 이름과 월급을 출력 해보자.

1.JONES가 받는 월급을 찾는다

SELECT ENAME,SAL     (=2975)
FROM EMP
WHERE ENAME = 'JONES';

2.1번의 결과로 쿼리를 구현한다.

SELECT ENAME, SAL
FROM EMP
WHERE SAL = 2975;

3.SubQuery로 구현 해보자.

SELECT ENAME, SAL
FROM EMP
WHERE SAL =
 (SELECT SAL  FROM EMP
WHERE ENAME = 'JONES');

Q11. EMPLOYEE 에서 나승원과 같은 부서에 근무하는 사원의 이름을 출력 해보자.

SELECT EMP_NAME
FROM EMPLOYEE
WHERE DEPT_ID = (SELECT DEPT_ID FROM EMPLOYEE
WHERE EMP_NAME = '나승원');

---

Q12. EMPLOYEE 에서 나승원과 같은 직업을 가진 사원의 이름과 직업ID,봉급을 출력하자
단 봉급은 나승원 보다 많이 받는 사원의 정보를 출력 한다.

SELECT EMP_NAME,JOB_ID,SALARY
FROM EMPLOYEE
WHERE JOB_ID = (SELECT JOB_ID FROM EMPLOYEE
WHERE EMP_NAME = '나승원') AND SALARY > (SELECT SALARY
FROM EMPLOYEE WHERE EMP_NAME = '나승원');

Q13.EMPLOYEE 사원 테이블에서 가장 작은 봉급과 같은 봉급을 받는 사원의 이름, 직업 아이디,봉급을 출력하자.

SELECT EMP_NAME,JOB_ID,SALARY
FROM EMPLOYEE
WHERE SALARY = (SELECT MIN(SALARY) FROM EMPLOYEE);

Q14.부셔별 최대 봉급의 합(18100000)과 같은 봉급의 합을 받은 부서이름과 봉급의 합을 구해보자.

SELECT DEPT_ID,SUM(SALARY)
FROM EMPLOYEE
LEFT JOIN DEPARTMENT USING(DEPT_ID)
GROUP BY DEPT_ID, DEPT_NAME
HAVING SUM(SALARY) = (SELECT MAX(SUM(SALARY))
FROM EMPLOYEE
GROUP BY DEPT_ID);

Q15.부서별 최소 봉급과 같은 봉급을 받는 사원의 사원번호와 사원의 이름을 출력하자 IN

SELECT EMP_ID,EMP_NAME
FROM EMPLOYEE
WHERE SALARY IN (SELECT MIN(SALARY)
FROM EMPLOYEE 
GROUP BY DEPT_ID);

Q16. 전체 직원에 대한 관리자와 직원을 구분해서 표시해보자. 사원번호,사원의 이름 , 구분(관리자,직원)을 출력 IN

SELECT EMP_ID,EMP_NAME,
CASE
WHEN EMP_ID IN ( SELECT MGR_ID FROM EMPLOYEE) THEN '관리자'
ELSE '직원' END AS 구분
FROM EMPLOYEE
ORDER BY 3,1;

Q17.과장직급 보다 급여가 많은 대리 직급의 직원을 조회해 보자. 사원의 이름 봉급을 출력 해보자. ANY
< ANY : 비교 대상 중 최대값 보다 작은
.> ANY : 비교 대상 중 최소값 보다 클때
= ANY : IN 연산자와 동일

SELECT EMP_NAME,SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_ID)
WHERE JOB_TITLE = '대리'
AND SALARY > ANY(
SELECT SALARY
FROM EMPLOYEE
JOIN JOB USING (JOB_ID)
WHERE JOB_TITLE = '과장');

Q.18 모든 과장들의 직급보다 급여가 많은 대리 직급의 직원을 조회해 보자. _ALL
< ALL : 비교 대상 중 최소 값보다 적을 때
.> ALL: 비교대상중 최대 값 보다 클 때

SELECT EMP_NAME,SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_ID)
WHERE JOB_TITLE = '대리'
AND SALARY > ALL(
SELECT SALARY
FROM EMPLOYEE
JOIN JOB USING (JOB_ID)
WHERE JOB_TITLE = '과장');

Q19.자기 직급의 평균 급여를 받는 직원을 조회하자. 이름(EMP_NAME) , 직급(JOB_TITLE) ,봉급(SALARAY)

박하일 -> 과장 -> 2600000
정도연 차장 2600000

==============================================

직급별 평균 급여

SELECT JOB_TITLE,TRUNC(AVG(SALARY),-5)
FROM EMPLOYEE
JOIN JOB USING(JOB_ID)
GROUP BY (JOB_ID,JOB_TITLE);

==============================================

SELECT EMP_NAME,JOB_TITLE,SALARY
FROM EMPLOYEE
LEFT JOIN JOB USING(JOB_ID)
WHERE (NVL(JOB_ID,' '),SALARY) IN
(SELECT NVL(JOB_ID,' '),
TRUNC(AVG(SALARY),-5)
FROM EMPLOYEE
GROUP BY JOB_ID)
ORDER BY JOB_ID;

Q.20 FROM 절을 이용해서 풀어보자.

SELECT EMP_NAME, JOB_TITLE , SALARY
FROM (SELECT JOB_ID, TRUNC(AVG(SALARY),-5) AS JOBAVG
FROM EMPLOYEE
GROUP BY (JOB_ID) ) V
JOIN EMPLOYEE E ON
(JOBAVG = SALARY AND
NVL(E.JOB_ID,' ')=NVL(V.JOB_ID,' '))
LEFT JOIN JOB J ON (E.JOB_ID = J.JOB_ID)
ORDER BY V.JOB_ID;

Q21. SUBQUERY _ Correlated Subquery : 메인 쿼리에서 고려된 각 후보 행들에 대해 서브쿼리와 다른 결과를 반환해야
하는 경우 (메인 쿼리에서 처리되는 각 행의 값에 따라 리턴이 달라져야 하는 경우)에 유용하다.

SELECT EMP_NAME,JOB_TITLE,SALARY
FROM EMPLOYEE E
LEFT JOIN JOB J ON (E.JOB_ID = J.JOB_ID)
WHERE SALARY = (
SELECT TRUNC(AVG(SALARY),-5)
FROM EMPLOYEE
WHERE NVL(JOB_ID,' ') = NVL(E.JOB_ID,' ')
)
ORDER BY E.JOB_ID;


좋은 웹페이지 즐겨찾기